【自学】Java核心技术卷1_5.6枚举Enum

最重要的参考博客,其他参考博客1博客2

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);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值