zoukankan      html  css  js  c++  java
  • JAVA-Enum 枚举

    【参考】枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
    说明:枚举其实就是特殊的类,域成员均为常量,且构造方法被默认强制是私有。
    正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON。

    创建一个枚举类

    public enum DayEnum {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
    }

    使用

    public class EnumTest {
        DayEnum day;
    
        public EnumTest(DayEnum day) {
            this.day = day;
        }
    
        public void tellItLikeItIs() {
            switch (day) {
                case MONDAY:
                    System.out.println("Mondays are bad.");
                    break;
                case FRIDAY:
                    System.out.println("Fridays are better.");
                    break;
                case SATURDAY: case SUNDAY:
                    System.out.println("Weekends are best.");
                    break;
                default:
                    System.out.println("Midweek days are so-so.");
                    break;
            }
        }
    
        public static void main(String[] args) {
            EnumTest firstDay = new EnumTest(DayEnum.MONDAY);
            firstDay.tellItLikeItIs();
            EnumTest thirdDay = new EnumTest(DayEnum.WEDNESDAY);
            thirdDay.tellItLikeItIs();
            EnumTest fifthDay = new EnumTest(DayEnum.FRIDAY);
            fifthDay.tellItLikeItIs();
    
            EnumTest sixthDay = new EnumTest(DayEnum.SATURDAY);
            sixthDay.tellItLikeItIs();
            EnumTest seventhDay = new EnumTest(DayEnum.SUNDAY);
            seventhDay.tellItLikeItIs();
        }
    }

    带构造器枚举类

    当存在字段和方法时,枚举常量列表必须以分号结尾,且定义枚举常量在字段和方法之前

    枚举类型的构造函数必须是私有(没有修饰符默认为 private),不能自己手动调用​​枚举类的构造函数,JVM 会自动创建在枚举类中定义的常量。所以看似一样的枚举值一定不相等,因为这可能不是同一个对象实例

    /**
     * 行星上一个物体的重力和重量
     */
    public enum Planet {
        MERCURY(3.303e+23, 2.4397e6),
        VENUS(4.869e+24, 6.0518e6),
        EARTH(5.976e+24, 6.37814e6),
        MARS(6.421e+23, 3.3972e6),
        JUPITER(1.9e+27, 7.1492e7),
        SATURN(5.688e+26, 6.0268e7),
        URANUS(8.686e+25, 2.5559e7),
        NEPTUNE(1.024e+26, 2.4746e7);
    
        // 以公斤为单位的
        private final double mass;
        // 以米为单位的
        private final double radius;
    
        Planet(double mass, double radius) {
            this.mass = mass;
            this.radius = radius;
        }
    
        private double mass() {
            return mass;
        }
    
        private double radius() {
            return radius;
        }
    
        // 万有引力常数 (m3 kg-1 s-2)
        public static final double G = 6.67300E-11;
    
        double surfaceGravity() {
            return G * mass / (radius * radius);
        }
    
        double surfaceWeight(double otherMass) {
            return otherMass * surfaceGravity();
        }
    }

    使用

    public static void main(String[] args) {
        double earthWeight = Double.parseDouble("175");
        double mass = earthWeight / EARTH.surfaceGravity();
        for (Planet p : Planet.values()) {
            System.out.printf("你在 %s 上的体重是 %f%n", p, p.surfaceWeight(mass));
        }
    }

     

    Enum  相关方法

    public static void main(String[] args) {
        // 获取所有枚举常量
        DayEnum[] values = DayEnum.values();
        for (DayEnum value : values) {
            System.out.print(value);
            // 枚举常量在枚举类中的序号,零开始
            System.out.println("	" + value.ordinal());
        }
    
        // 获取指定枚举常量,若不存在会报异常
        System.out.println(DayEnum.valueOf("SATURDAY"));
        System.out.println(DayEnum.valueOf(DayEnum.class, "SATURDAY"));
    
        // 比较枚举常量,与 == 方式相同,返回布尔值
        System.out.println(DayEnum.FRIDAY.equals(DayEnum.FRIDAY));
        // 比较枚举常量,采用 ordinal 序号方式,返回数字
        System.out.println(DayEnum.FRIDAY.compareTo(DayEnum.FRIDAY));
    }

    反编译 DayEnum

    所有枚举类都隐式继承了抽象类 java.lang.Enum,用 javap 工具可以看到。所以枚举类不能继承其他类,JAVA 中为单继承,多实现

    枚举常量会隐式被修饰成公共的静态常量,即枚举常量只会有一个实例,比较时可以使用 ==,枚举类的 equals 方法是 final 修饰

    public final class javaenum.DayEnum extends java.lang.Enum<javaenum.DayEnum> {
      public static final javaenum.DayEnum SUNDAY;
    
      public static final javaenum.DayEnum MONDAY;
    
      public static final javaenum.DayEnum TUESDAY;
    
      public static final javaenum.DayEnum WEDNESDAY;
    
      public static final javaenum.DayEnum THURSDAY;
    
      public static final javaenum.DayEnum FRIDAY;
    
      public static final javaenum.DayEnum SATURDAY;
    
      public static javaenum.DayEnum[] values();
        Code:
           0: getstatic     #1                  // Field $VALUES:[Ljavaenum/DayEnum;
           3: invokevirtual #2                  // Method "[Ljavaenum/DayEnum;".clone:()Ljava/lang/Object;
           6: checkcast     #3                  // class "[Ljavaenum/DayEnum;"
           9: areturn
    
      public static javaenum.DayEnum valueOf(java.lang.String);
        Code:
           0: ldc           #4                  // class javaenum/DayEnum
           2: aload_0
           3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
           6: checkcast     #4                  // class javaenum/DayEnum
           9: areturn
    
      static {};
        Code:
           0: new           #4                  // class javaenum/DayEnum
           3: dup
           4: ldc           #7                  // String SUNDAY
           6: iconst_0
           7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
          10: putstatic     #9                  // Field SUNDAY:Ljavaenum/DayEnum;
          13: new           #4                  // class javaenum/DayEnum
          16: dup
          17: ldc           #10                 // String MONDAY
          19: iconst_1
          20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
          23: putstatic     #11                 // Field MONDAY:Ljavaenum/DayEnum;
          26: new           #4                  // class javaenum/DayEnum
          29: dup
          30: ldc           #12                 // String TUESDAY
          32: iconst_2
          33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
          36: putstatic     #13                 // Field TUESDAY:Ljavaenum/DayEnum;
          39: new           #4                  // class javaenum/DayEnum
          42: dup
          43: ldc           #14                 // String WEDNESDAY
          45: iconst_3
          46: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
          49: putstatic     #15                 // Field WEDNESDAY:Ljavaenum/DayEnum;
          52: new           #4                  // class javaenum/DayEnum
          55: dup
          56: ldc           #16                 // String THURSDAY
          58: iconst_4
          59: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
          62: putstatic     #17                 // Field THURSDAY:Ljavaenum/DayEnum;
          65: new           #4                  // class javaenum/DayEnum
          68: dup
          69: ldc           #18                 // String FRIDAY
          71: iconst_5
          72: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
          75: putstatic     #19                 // Field FRIDAY:Ljavaenum/DayEnum;
          78: new           #4                  // class javaenum/DayEnum
          81: dup
          82: ldc           #20                 // String SATURDAY
          84: bipush        6
          86: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
          89: putstatic     #21                 // Field SATURDAY:Ljavaenum/DayEnum;
          92: bipush        7
          94: anewarray     #4                  // class javaenum/DayEnum
          97: dup
          98: iconst_0
          99: getstatic     #9                  // Field SUNDAY:Ljavaenum/DayEnum;
         102: aastore
         103: dup
         104: iconst_1
         105: getstatic     #11                 // Field MONDAY:Ljavaenum/DayEnum;
         108: aastore
         109: dup
         110: iconst_2
         111: getstatic     #13                 // Field TUESDAY:Ljavaenum/DayEnum;
         114: aastore
         115: dup
         116: iconst_3
         117: getstatic     #15                 // Field WEDNESDAY:Ljavaenum/DayEnum;
         120: aastore
         121: dup
         122: iconst_4
         123: getstatic     #17                 // Field THURSDAY:Ljavaenum/DayEnum;
         126: aastore
         127: dup
         128: iconst_5
         129: getstatic     #19                 // Field FRIDAY:Ljavaenum/DayEnum;
         132: aastore
         133: dup
         134: bipush        6
         136: getstatic     #21                 // Field SATURDAY:Ljavaenum/DayEnum;
         139: aastore
         140: putstatic     #1                  // Field $VALUES:[Ljavaenum/DayEnum;
         143: return
    }

     

    Enum 源码

    /**
     * 使用枚举类型作为 Collection 或 Map 中 Key 的类型时
     * 可用 {@linkplain java.util.EnumSet set} 和 {@linkplain java.util.EnumMap map} 实现,专业且高效
     */
    public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
        // 枚举常量的名称,获取时使用{@link #toString}方法而不是访问此字段
        private final String name;
    
        // 此方法主要用于在特殊情况下使用
        public final String name() {
            return name;
        }
    
        // 此枚举常数的序数(其位置在枚举声明中,分配初始常量序数为零)
        // 专门设计供复杂基于枚举的数据结构使用,例如 {@link java.util.EnumSet} 和 {@link java.util.EnumMap}
        private final int ordinal;
    
        public final int ordinal() {
            return ordinal;
        }
    
        /**
         * 唯一构造函数。程序员无法调用,由编译器调用
         * @param name    枚举常量的名称,用于声明它的标识符
         * @param ordinal 枚举常量的序数(声明它在枚举中的位置,初始常量的序数为零)
         */
        protected Enum(String name, int ordinal) {
            this.name = name;
            this.ordinal = ordinal;
        }
    
        // 返回声明中包含的此枚举常量的名称,可以覆盖该方法
        public String toString() {
            return name;
        }
    
        public final boolean equals(Object other) {
            return this == other;
        }
    
        public final int hashCode() {
            return super.hashCode();
        }
    
        // 保证了枚举类永远不会被克隆
        protected final Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    
        // 返回负整数,零或正整数
        // 枚举常量只能与同一枚举类型的其他枚举常量相比较。此方法实现是根据 ordinal 值比较
        public final int compareTo(E o) {
            Enum<?> other = (Enum<?>) o;
            Enum<E> self = this;
            if (self.getClass() != other.getClass() && self.getDeclaringClass() != other.getDeclaringClass())
                throw new ClassCastException();
            return self.ordinal - other.ordinal;
        }
    
        // 返回与此枚举常量的枚举类型对应的 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;
        }
    
        /**
         * @param enumType 枚举类型的 Class 对象,用于从中返回常量
         * @param name     要返回的常量的名称
         * @param <T>      要返回常量的其枚举类型
         * @return 具有指定名称的指定枚举类型的枚举常量
         */
        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);
        }
    
        // 枚举类不能有finalize方法
        protected final void finalize() {}
    
        // 默认防止反序列化
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            throw new InvalidObjectException("can't deserialize enum");
        }
    
        private void readObjectNoData() throws ObjectStreamException {
            throw new InvalidObjectException("can't deserialize enum");
        }
    }

    https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

    https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.9

    https://www.ibm.com/developerworks/cn/java/j-lo-enum/index.html

    https://blog.csdn.net/javazejian/article/details/71333103

  • 相关阅读:
    hdu4829 带权并查集(题目不错)
    hdu4829 带权并查集(题目不错)
    洛谷 P1076 寻宝(模拟 && 剪枝)
    洛谷 P1981 表达式求值(模拟)
    洛谷 P2239 螺旋矩阵(模拟 && 数学)
    洛谷 P2118 比例简化(枚举)
    洛谷 P3956 棋盘(记忆化搜索)
    洛谷 P5018 对称二叉树(搜索)
    洛谷 P5016 龙虎斗(模拟)
    洛谷 P1563 玩具谜题(模拟)
  • 原文地址:https://www.cnblogs.com/jhxxb/p/10536948.html
Copyright © 2011-2022 走看看