Depth understanding of enumeration class

In-depth understanding of enumeration

JVM recently finished learning the knowledge, think of enumeration as so heterogeneous, it is from the perspective of the byte code to analyze it. Enumeration of relevant explanations, a lot of very detailed blog, here we are in terms of byte code again come to know about it.

Enumeration class is a special class that can have its own fields, methods, may implement one or more interfaces can define your own constructor.

1. The enumeration class inheritance structure:

2. The enumeration class and normal class differences:

(1) enumeration class may implement one or more interfaces using enum defined java.lang.Enum enumeration class inherits default class, Object class inheritance instead, and therefore can not display the enumeration inherit other inherited (single inheritance limitations, but can implement interfaces). Where "java.lang.Enum" to achieve a "Comparable" and "Serializable" interface.

(2) use enum definition, non-abstract class enumeration is used by default final modification, and therefore can not enumerate classes subclass.

(3) enumeration class constructor is possible only with the private access specifier, if access specifier is omitted constructors, use the private modifier default; if the specified mandatory access control at only specify private modifiers.

All instances (4) enum class must be listed in the first line of the display enumeration class, otherwise the Enumeration class never be able to produce examples. These are listed in real time, the system will automatically add public static final modifier, programmers do not need to add display.

(5) enumeration class provides default values ​​a method that returns an array of enumerated example, the method can be easily traverse all the enumerated value.

In order to better explain, above these differences, let's define an enumeration type, use "javap -c" to decompile it

public enum  Season {
   SPRING("春"),SUMMER("夏"),AUTUMN("秋"),WINTTER("冬");
   private String name;

   Season(String name) {
      this.name = name;
   }
}

Decompile can get this information:

"D:\Program Files\Java\jdk1.8.0_77\bin\javap.exe" -c com.bigdata.juc.enums.Season
Compiled from "Season.java"
public final class com.bigdata.juc.enums.Season extends java.lang.Enum<com.bigdata.juc.enums.Season> {
   //所定义的所有实例都变为了final修饰的了,并且是static类型的
  public static final com.bigdata.juc.enums.Season SPRING;

  public static final com.bigdata.juc.enums.Season SUMMER;

  public static final com.bigdata.juc.enums.Season AUTUMN;

  public static final com.bigdata.juc.enums.Season WINTTER;
  //自动提供了values方法
  public static com.bigdata.juc.enums.Season[] values();
    Code:
       0: getstatic     #1                  // Field $VALUES:[Lcom/bigdata/juc/enums/Season;
       3: invokevirtual #2                  // Method "[Lcom/bigdata/juc/enums/Season;".clone:()Ljava/lang/Object;
       6: checkcast     #3                  // class "[Lcom/bigdata/juc/enums/Season;"
       9: areturn
  //复写valueoff方法
  public static com.bigdata.juc.enums.Season valueOf(java.lang.String);
    Code:
       0: ldc           #4                  // class com/bigdata/juc/enums/Season
       2: aload_0
       3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #4                  // class com/bigdata/juc/enums/Season
       9: areturn
//枚举类的对象实例化工作是在静态块中完成,无需用户手动实例化,也就是说上面的所定义的四个对象都是在静态块中完成实例化的
  static {};
    Code:
       //第一次,实例化枚举类并赋值给实例SPRING
       0: new           #4                  // class com/bigdata/juc/enums/Season
       3: dup
       4: ldc           #8                  // String SPRING
       6: iconst_0
       7: ldc           #9                  // String 春
       9: invokespecial #10                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
      12: putstatic     #11                 // Field SPRING:Lcom/bigdata/juc/enums/Season;
      //第二次,实例化枚举类并赋值给实例SUMMER
      15: new           #4                  // class com/bigdata/juc/enums/Season
      18: dup
      19: ldc           #12                 // String SUMMER
      21: iconst_1
      22: ldc           #13                 // String 夏
      24: invokespecial #10                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
      27: putstatic     #14                 // Field SUMMER:Lcom/bigdata/juc/enums/Season;
      //第三次,实例化枚举类并赋值给实例AUTUMN
      30: new           #4                  // class com/bigdata/juc/enums/Season
      33: dup
      34: ldc           #15                 // String AUTUMN
      36: iconst_2
      37: ldc           #16                 // String 秋
      39: invokespecial #10                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
      42: putstatic     #17                 // Field AUTUMN:Lcom/bigdata/juc/enums/Season;
       //第四次,实例化枚举类并赋值给实例WINTTER
      45: new           #4                  // class com/bigdata/juc/enums/Season
      48: dup
      49: ldc           #18                 // String WINTTER
      51: iconst_3
      52: ldc           #19                 // String 冬
      54: invokespecial #10                 // Method "<init>":(Ljava/lang/String;ILjava/lang/String;)V
      57: putstatic     #20                 // Field WINTTER:Lcom/bigdata/juc/enums/Season;
      60: iconst_4
          //创建一个引用类型的数组,这个数组就是Season
      61: anewarray     #4                  // class com/bigdata/juc/enums/Season
          //复制栈顶一个字长的数据,将复制后的数据压栈。
      64: dup
          //0(int)值入栈。
      65: iconst_0
          //获取静态字段的值。
      66: getstatic     #11                 // Field SPRING:Lcom/bigdata/juc/enums/Season;
          //将栈顶引用类型值保存到指定引用类型数组的指定项。
      69: aastore
          //复制栈顶一个字长的数据,将复制后的数据压栈。
      70: dup
          //1(int)值入栈。
      71: iconst_1
          //获取静态字段的值
      72: getstatic     #14                 // Field SUMMER:Lcom/bigdata/juc/enums/Season;
          //将栈顶引用类型值保存到指定引用类型数组的指定项。
      75: aastore
      76: dup
      77: iconst_2
      78: getstatic     #17                 // Field AUTUMN:Lcom/bigdata/juc/enums/Season;
      81: aastore
      82: dup
      83: iconst_3
      84: getstatic     #20                 // Field WINTTER:Lcom/bigdata/juc/enums/Season;
      87: aastore
      88: putstatic     #1                  // Field $VALUES:[Lcom/bigdata/juc/enums/Season;
      91: return
}

Process finished with exit code 0

You can find it completed a total of two things in the static block:

(1) instantiate the class and assigned to enumerate instances enumerated

(2) create a reference to the type of array and an array assignment, which is the reason for the enumeration method values ​​the array can be.

Because enumeration class inherits from "java.lang.Enum" class, it automatically inherits some of the methods of the class:

Quote from the "Crazy Gang JAVA handouts"

Enumerate the class member variables, methods and constructors

Enumeration class is also a class, but it is a special category, so it can be defined as member variables, methods and constructors. Or the above piece of code

public enum  Season {
    //枚举实例,必须要定义在第一行
   SPRING("春"),SUMMER("夏"),AUTUMN("秋"),WINTTER("冬");
    //定义了成员变量
   private String name;
   //定义了构造器,默认为private类型,无论是否显示修饰
   Season(String name) {
      this.name = name;
   }
}

In fact it done automatically instantiate the underlying work, in front of our decompile have seen this, it is done in a static object is instantiated block work. Like this:

public static final  SPRING=new SPRING("春");
public static final  SPRING=new SUMMER("夏");
public static final  SPRING=new AUTUMN("秋");
public static final  SPRING=new WINTTER("冬");

4. enumeration class implements the interface

Although it is impossible to enumerate inherit other classes, but can still implement other interfaces, because the interface does not have the limitations of single inheritance. On the enumeration class that implements the interface and implementation of the interface is the same general category, there is no essential difference.

Definition of the interface:

public interface GenderDesc {
    void info();
}

Enum class implements this interface:

//实现接口,并且以内部类的形式
public enum Gender implements GenderDesc
{
    // public static final Gender MALE = new Gender("男");
    MALE("男") {
        public void info() {
            System.out.println("gender male information");
        }
    },
    FEMALE("女") {

        public void info() {
            System.out.println("gender female information");
        }
    };
    private String name;
    private Gender(String name) {
        this.name = name;
    }
}
public class enumTest {
    public static void main(String[] args) {
        // 通过valueof方法获取指定枚举类的值
        Gender gf = Enum.valueOf(Gender.class, "FEMALE");
        Gender gm = Enum.valueOf(Gender.class, "MALE");
        System.out.println(gf + " is stand for " + gf.getName());
        System.out.println(gm + " is stand for " + gm.getName());
        gf.info();
        gm.info();
    }
}

Gender class at compile time, will generate three classes "Gender.class", "Gender $ 1.class" and "Gender $ 2.class", which Gender $ 1 and Gender $ 2 anonymous inner classes are represented.

Note 1: For the above stated non-abstract class enumeration, use the "final" modified, abstract enumeration class, using the abstract modification, this can be through "javap -c Gender.class" see:

D:\Project\JUCDmo\other\target\classes\com\bigdata\juc\enums>javap -c Gender.class
Compiled from "Gender.java"
//使用abstract修饰,因为尽管匿名内部实例MALE和FEMALE中实现了info方法,但是在Gender类中并没有实现info方法,所以它仍然会被认为是抽象的,除非显示的实现info方法
public abstract class com.bigdata.juc.enums.Gender extends java.lang.Enum<com.bigdata.juc.enums.Gender> implements com.bigdata.juc.enums.GenderDesc {
  public static final com.bigdata.juc.enums.Gender MALE;

  public static final com.bigdata.juc.enums.Gender FEMALE;

The "Gender $ 1.class"

D:\Project\JUCDmo\other\target\classes\com\bigdata\juc\enums>javap -p Gender$1.class
Compiled from "Gender.java"
//使用final修饰   
final class com.bigdata.juc.enums.Gender$1 extends com.bigdata.juc.enums.Gender {
  com.bigdata.juc.enums.Gender$1(java.lang.String, int, java.lang.String);
  public void info();
}

Note 2: The two methods of enumeration values ​​exhibit different behavior, they refer to the difference in the output info, and other manifestations of behavior nothing special.

Original link: https://www.cnblogs.com/MarchThree/p/3720468.html

The abstract class enumeration method comprising

When the enumeration class defines an abstract method can not be used to enumerate the abstract keyword is defined as an abstract class (because the system will automatically add the abstract keyword for it), but because you need to display enumeration class to create enumerated values, so the definition of each It must provide an implementation for abstract methods when enumeration value, otherwise it will appear to compile exception.

enum Operation {
    PLUS {
        public double eval(double x, double y) {
            return x + y;
        }
    },
    MINS {
        public double eval(double x, double y) {
            return x - y;
        }
    },
    TIMES {
        public double eval(double x, double y) {
            return x * y;
        }
    },
    DIVIDE {
        public double eval(double x, double y) {
            if (y == 0) {
                return -1;
            }
            return x / y;
        }
    };
    //为枚举类定义抽象方法,具体由枚举值提供实现
    public abstract double eval(double x, double y);
}
public class OperationTest {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(Operation.PLUS.eval(1, 2));
        System.out.println(Operation.DIVIDE.eval(1, 0));
    }
}

Part of the result of decompilation:

D:\Project\JUCDmo\other\target\classes\com\bigdata\juc\enums>javap -c Operation.class
Compiled from "OperationTest.java"
//类名为abstract修饰    
abstract class com.bigdata.juc.enums.Operation extends java.lang.Enum<com.bigdata.juc.enums.Operation> {
  public static final com.bigdata.juc.enums.Operation PLUS;

  public static final com.bigdata.juc.enums.Operation MINS;

  public static final com.bigdata.juc.enums.Operation TIMES;

  public static final com.bigdata.juc.enums.Operation DIVIDE;

  public static com.bigdata.juc.enums.Operation[] values();
    Code:
       0: getstatic     #2                  // Field $VALUES:[Lcom/bigdata/juc/enums/Operation;
       3: invokevirtual #3                  // Method "[Lcom/bigdata/juc/enums/Operation;".clone:()Ljava/lang/Object;
       6: checkcast     #4                  // class "[Lcom/bigdata/juc/enums/Operation;"
       9: areturn

  public static com.bigdata.juc.enums.Operation valueOf(java.lang.String);
    Code:
       0: ldc           #5                  // class com/bigdata/juc/enums/Operation
       2: aload_0
       3: invokestatic  #6                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #5                  // class com/bigdata/juc/enums/Operation
       9: areturn

  public abstract double eval(double, double);

  com.bigdata.juc.enums.Operation(java.lang.String, int, com.bigdata.juc.enums.Operation$1);
    Code:
       0: aload_0
       1: aload_1
       2: iload_2
       3: invokespecial #1                  // Method "<init>":(Ljava/lang/String;I)V
       6: return

  static {};
    ……

Original link: https://blog.csdn.net/uni_ys/article/details/60956718 https://www.cnblogs.com/MarchThree/p/3720467.html

Introduction 6. Use enumeration

In a single embodiment, enum

```java
package com.bigdata.juc.singleton;
/*
 * 枚举类型:表示该类型的对象是有限的几个
 * 我们可以限定为一个,就成了单例
 */
enum EnumSingleton{
    //等价于 public static final INSTANCE=new EnumSingleton();
    INSTANCE
}
public class Singleton2 {
    public static void main(String[] args) {
        EnumSingleton s = EnumSingleton.INSTANCE;
        System.out.println(s);
    }
}
```

7. values ​​method on enumeration class?

Enumeration values (), neither from the Java.lang.Enum, nor from the interface Enum achieved, it is in the process of compiling their own produce, and in front of the decompilation process, we also see to this point, but we also see that it is actually generated an underlying reference type array, then this method returns the enumeration values array. Can refer to its use on enumeration class of enum values () method

Want in-depth understanding of its origin, you can refer to the blog in-depth understanding of Java enumeration type (enum)

Guess you like

Origin www.cnblogs.com/cosmos-wong/p/11919418.html