Java Enum学习笔记

Java enum学习笔记


一. 什么是enum

enum是Java SE5中新增加的关键字,用来声明一个枚举类型集。在enum没有加入到Java之前,对于枚举一个有限集合的一般做法是创造一个整型的常量集。创造整型常量级的做法会带来一定的风险,即我们没有办法控制集合中的合法元素。比如用整数1到5表示5个状态,但是在调用某一含有状态整数的方法是,输入整数参数6并不会造成编译错误,然而在运行的时候则会产生异常。enum的加入使得程序可以在编译的时候就有效的进行类型控制,确保在需要的地方使用的都是集合中定义的元素。

enum的基本定义格式如下:

public enum EnumDemo {
	ELEMENT_A, ELEMENT_B, ELEMENT_C
}

其中所有枚举类型均用大写标注,不同enum之间用逗号隔开。


二. enum的实质

编译上述enum例子生成EnumDemo.class,然后使用javap命令,我们就能获得JVM对于enum编译后的文件大概。如下为EnumDemo.class的大致内容:

public final class EnumDemo extends java.lang.Enum{
    public static final EnumDemo ELEMENT_A;
    public static final EnumDemo ELEMENT_B;
    public static final EnumDemo ELEMENT_C;
    static {};
    public static EnumDemo[] values();
    public static EnumDemo valueOf(java.lang.String);
}
所以我们可以看出:

1. EnumDemo在编译后是一个继承了java.lang.Enum类的public final class。

2. 所有列举的元素都是都是一个EnumDemo的对象。

3. EnumDemo类除了继承了Enum类的所有方法以外,JVM在编译的时候还插入了values()方法,并且重载了valueOf()方法。


综上所述,enum的实质是一个继承Enum类的final类,它包含了所有列举出的以其本身为类型的静态final对象元素(枚举元素)。它除了继承Enum的方法外,还被JVM添加了values和valueOf方法。


当然我们还可以为enum添加新的方法,自定义enum的构造函数,以及让列举的元素覆盖enum中定义的方法。如下的枚举类型Language就展示enum更丰富的定义。每一个Language枚举元素包含了使用国家和使用人口总数属性,Language还重新覆盖了Enum中的toString方法。在CHINESE这个元素中,它又重写了Language中定义的toString方法。代码如下:

package enumTest;

public enum Language {
	CHINESE(/* constructor parameters */"China", 1.2d) {
		/* overrided method */
		@Override
		public String toString() {
			return "CHINESE";
		}
	},
	JAPANESE("Japan", 0.1d), ENGLISH("England", 0.03d), FRENCH("France", 0.05d), GERMAN(
			"Germany", 0.06d);

	private String country;
	private double population;

	private Language() {

	}

	private Language(String country, double population) {
		this.country = country;
		this.population = population;
	}

	public String getCountry() {
		return country;
	}

	public double getPopulation() {
		return population;
	}

	enum Level {
		BEGINNER, MIDDLE_LEVEL, ADEVENCED
	}

	@Override
	public String toString() {
		String s = this.name();
		String lower = s.substring(1).toLowerCase();
		return s.charAt(0) + lower;
	}
}


三. enum的应用(包含EnumSet和EnumMap的使用)

enum最值得注意的应用就是它可以在switch语句中被使用,这样我们就可以轻松地处理不同枚举情况。
另外针对enum类型,我们可以使用相关的EnumSet和EnumMap来保存信息。EnumSet只允许包含某个enum类型的对象,EnumMap的限制在于key type只能是某个enum类型。

以下是一个应用上述Language枚举类小例子,基本展现enum的各方面使用:
package enumTest;

import static enumTest.Language.CHINESE;
import static enumTest.Language.Level.ADEVENCED;
import static enumTest.Language.Level.BEGINNER;
import static enumTest.Language.Level.MIDDLE_LEVEL;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map.Entry;

public class LearningLanguage {

	public static void main(String[] args) {
		Student st = new Student("XiaoZhang", CHINESE);
		st.learn(Language.JAPANESE);
		st.learn(Language.ENGLISH);
		st.learn(Language.FRENCH);
		st.passExame(Language.ENGLISH);
		st.practise(Language.FRENCH);
		System.out.println(st.languageAbility());
	}

}

class Student {
	private String name;
	private Language motherTongue;
	private String nationality;
	private EnumSet<Language> learningLanguage;
	private EnumMap<Language, Language.Level> languageLevel;

	public Student(String name, Language motherTongue) {
		this.name = name;
		this.motherTongue = motherTongue;
		setNationality();
		learningLanguage = EnumSet.noneOf(Language.class);
		languageLevel = new EnumMap<Language, Language.Level>(Language.class);
		languageLevel.put(this.motherTongue, ADEVENCED);
	}

	private void setNationality() {
		switch (this.motherTongue) {
		case CHINESE:
			this.nationality = "Chinese";
			break;
		case JAPANESE:
			this.nationality = "Japanese";
			break;
		case ENGLISH:
			this.nationality = "English";
			break;
		case FRENCH:
			this.nationality = "French";
			break;
		case GERMAN:
			this.nationality = "German";
			break;
		}
	}

	public void learn(Language language) {
		this.learningLanguage.add(language);
		languageLevel.put(language, BEGINNER);
	}

	public void passExame(Language language) {
		languageLevel.put(language, MIDDLE_LEVEL);
	}

	public void practise(Language language) {
		this.learningLanguage.remove(language);
		languageLevel.put(language, ADEVENCED);
	}

	public String languageAbility() {
		StringBuffer sb = new StringBuffer();
		sb.append(this.name + " speaks " + motherTongue
				+ " as mother language.\n" + this.name + "'s nationality is "
				+ this.nationality + ".  \n\n");
		sb.append(this.name + " is learning ");
		for (Language lg : learningLanguage) {
			sb.append(lg.toString() + " ");
		}
		sb.append(". \n\n");
		sb.append(this.name + "'s language ability is shown as belows: \n");

		StringBuffer tmp = new StringBuffer();
		double total = 0d;
		for (Entry<Language, Language.Level> entry : languageLevel.entrySet()) {
			if (entry.getValue() != null) {
				sb.append(entry.getKey().toString() + " : "
						+ entry.getValue().toString() + " \n");
				tmp.append(entry.getKey().getCountry() + " ");
				total = total + entry.getKey().getPopulation();
			}
		}

		sb.append("\n" + this.name + " can travel in " + tmp.toString()
				+ ". And he can speak with " + String.format("%.2f", total)
				+ " billion people");
		return sb.toString();
	}
}

输出:
XiaoZhang speaks CHINESE as mother language.
XiaoZhang's nationality is Chinese.  

XiaoZhang is learning Japanese English . 

XiaoZhang's language ability is shown as belows: 
CHINESE : ADEVENCED 
Japanese : BEGINNER 
English : MIDDLE_LEVEL 
French : ADEVENCED 

XiaoZhang can travel in China Japan England France . And he can speak with 1.38 billion people



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值