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的使用)
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