Enumeration Calsses枚举类——实例有限且固定的类
- 此处枚举类型名称:Size
- Size类型包含的枚举常量:SMALL, MEDIUM, LARGE, EXTRA_LARGE
- 直接使用类型名定义枚举变量:Size s=Size.SMALL;
- 通过关键字enum创建枚举类型在编译后事实上也是一个类类型而且该类继承自java.lang.Enum类。如此声明的Size 其实是一个类class,这个类正好有四个实例对象,这个类不可能构造新实例对象,但可以添加域、构造器、方法(普通方法,抽象方法),不过构造器只有在构造枚举常量时由编译器调用,枚举类型还可以实现接口,也可以通过接口组织枚举类型(这个博客的例子很好)。
- Enum类的valueOf():
- valueOf(Class<T> enumType,String name):根据枚举变量名获取指定枚举类型的枚举常量
- 编译器生成的values()、valueOf():
- valueOf(String name):通过枚举常量名获取枚举常量
- values():获取枚举类所有枚举常量,作为数组返回
- 由于values()方法是由编译器插入到枚举类中的static方法,所以如果我们将枚举实例向上转型为Enum,那么values()方法将无法被调用,因为Enum类中并没有values()方法,编译器的valueOf()同理。
Enum类使用测试代码:
public class EnumTest {
public static void main(String[] args){
Size s=Size.SMALL;
s.info();
s=Size.valueOf("SMALL");
Size se=Enum.valueOf(Size.class,"SMALL");
System.out.println("s("+s+")==se("+se+")is "+s.equals(se));
//调用values()获得所有枚举常量输出name:label
for(Size s1:Size.values()){
System.out.println(s1.name()+"("+s1.getLabel()+")"+": "+s1.advise());
}
//Class类的getEnumConstants()获得所有枚举常量
for(Size s2:s.getDeclaringClass().getEnumConstants()){ //之前错用成s.getClass(),getClass()是Object类的方法
int index=s.compareTo(s2);
System.out.println(s.name()+" compare to "+s2.name()+" is "+index+" in index");
}
//枚举类型应用于switch
EnumTest et=new EnumTest();
et.enumSwitchTest(s);
//通过接口组织枚举类型
System.out.println(Descriptor.Longth.valueOf("LONG"));
System.out.println(Descriptor.Height.valueOf("HIGH"));
}
public void enumSwitchTest(Size s_case){
switch(s_case){
case SMALL:System.out.println("There is a SMALL size");break;
case MEDIUM:System.out.println("There is a MEDIUM size");break;
case LARGE:System.out.println("There is a LARGE size");break;
default:System.out.println("There is no size");break;
}
}
}
//一个.java文件最多有一个public类,并且源文件与此public类同名,所以这里不用public了
enum Size implements Descriptor { //Size{SMALL,MEDIUM,LARGE}
// 因为已经定义了带参数的构造器,所以在列出枚举值时必须传入对应的参数
SMALL("S"){
public String advise(){
return "Size for thin people";
}
}, //所有实例(枚举值)必须在枚举类的第一行显式地列出,否则这个枚举类将永远不能产生实例https://www.jianshu.com/p/46dbd930f6a2
MEDIUM("M"){
public String advise(){
return "Size for common people";
}
}, //列出这些实例(枚举值)时,系统会自动添加 public static final 修饰,无需程序员显式添加
LARGE("L"){
public String advise(){
return "Size for fat people";
}
}; //后面有定义其他域、方法时,常量一定要用分号":"结束
private String label; //自定义枚举变量
Size(String label){ //构造函数(一定要是 private 或 friendly 的)
this.label=label;
}
public String getLabel(){ //自定义普通方法
return label;
}
public String toString(){ //重写toString()
return this.ordinal()+":"+this.name()+"("+this.getLabel()+")";
}
public void info(){ //实现接口方法
System.out.println("This enum describe Size");
}
public abstract String advise(); //定义抽象方法
}
//通过接口组织枚举类型
interface Descriptor{
public void info();
enum Longth{SHORT,LONG};
enum Height{LOW,HIGH};
}
- 输出:
操作enum的工具类:EnumSet、EnumMap(具体参考API)
- EnumSet 是枚举类型的高性能Set实现。它要求放入它的枚举常量必须属于同一枚举类型,保证集合中的元素不重复
- EnumMap K是enum类型,V可以是任意类型,EnumMap只能接收同一枚举类型的实例作为键值,并且由于枚举类型实例的数量相对固定并且有限,所以EnumMap使用数组来存放与枚举类型对应的值,这使得EnumMap的效率非常高。
最后附上Enum源码:
常用:name,ordinal,构造器,ordinal(),name(),toString(),equals(),compareTo(),valueOf()
比较枚举类型是否相等用 == 即可,不需要用equals(),因为Enum类已经重写了equals()方法,用的就是 == 比较
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
private final String name; //枚举常量名
private final int ordinal; //顺序数
protected Enum(String name, int ordinal) { //构造器,编译器调用
this.name = name;
this.ordinal = ordinal;
}
public final int ordinal() { //返回当前枚举常量的顺序数
return ordinal;
}
public final String name() { //返回枚举常量名,不可覆盖
return name;
}
public String toString() { //和name()功能一样,但是能覆盖
return name;
}
public final boolean equals(Object other) { //可以直接用==比较
return this==other;
}
public final int hashCode() { //返回哈希值
return super.hashCode(); //Enum的hashCode重写了Object的同名方法,这里super调用Object的hashCode
}
//保证枚举常量不背克隆,保证其唯一性
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
//getClass()返回class对象
if (self.getClass() != other.getClass() && self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
//getDeclaringClass返回枚举常量对应类型的class对象
@SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}
//根据特定名称获取枚举常量
public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
}