Java Enum类型浅析

来源:互联网 发布:资金博弈指标公式源码 编辑:程序博客网 时间:2024/06/15 17:48

今天在code的时候看到如下定义的Enum类型,觉得很奇怪:

public enum Sex {NONE {@Overridepublic String getName() {// TODO Auto-generated method stubreturn "空";}},MAN {@Overridepublic String getName() {// TODO Auto-generated method stubreturn "男";}},WOMEN {@Overridepublic String getName() {// TODO Auto-generated method stubreturn "女";}};public abstract String getName();}

      印象中Enum类型应该是被翻译成final的类,而每个成员应该都是此类的实例,为什么还能加入abstract方法,而且还能被重写呢.

随后又写了一个类:

State:

public enum State {BUSY,LEISURE;}

     然后使用javap -p命令反编译了一下两个枚举对象生成的.class文件:

     首先是Sex.class,反编译结果如下:

//Compiled from "Sex.java"public abstract class test.he.enumeration.Sex extends java.lang.Enum<test.he.enumeration.Sex> {  public static final test.he.enumeration.Sex NONE;  public static final test.he.enumeration.Sex MAN;  public static final test.he.enumeration.Sex WOMEN;  private static final test.he.enumeration.Sex[] $VALUES;  public static test.he.enumeration.Sex[] values();  public static test.he.enumeration.Sex valueOf(java.lang.String);  private test.he.enumeration.Sex();  public abstract java.lang.String getName();  test.he.enumeration.Sex(java.lang.String, int, test.he.enumeration.Sex$1);  static {};}
    1. 发现这里的Sex类被声明成abstract的了.

     2.而且还发现系统还生成了另外3个.class文件:Sex$1.class、Sex$2.class和Sex$3.class


     编译其中一个Sex$1.class:

//Compiled from "Sex.java"final class test.he.enumeration.Sex$1 extends test.he.enumeration.Sex {  test.he.enumeration.Sex$1(java.lang.String, int);  public java.lang.String getName();}

     3.注意到这里的Sex$1已经变成包访问权限,而且被声明了final,并且继承了Sex


     再使用jd-gui反编译Sex$1.class:

 enum Sex$1{  Sex$1()  {    super(str, i, null);  }  public String getName() {    return "空";  }}
     4.这个其实就是我们重写后的新的enum类,构造方法也是包访问权限

     随后反编译了State.class文件:

//Compiled from "State.java"public final class test.he.enumeration.State extends java.lang.Enum<test.he.enumeration.State> {  public static final test.he.enumeration.State BUSY;  public static final test.he.enumeration.State LEISURE;  private static final test.he.enumeration.State[] $VALUES;  public static test.he.enumeration.State[] values();  public static test.he.enumeration.State valueOf(java.lang.String);  private test.he.enumeration.State();  static {};}

     5.发现这里的对象直接被声明成了final.


试着把abstract方法删除,直接在对象后面定义方法,发现反编译的结果大致一致

只是Sex没被声明任何关键字:public class Sex

可以理解为Sex中,可以有自己的对象,也可以有自己子类的对象,所以未声明任何关键字

在一般情况下,需要把共有方法声明为abstract方法,

 因为从public static final test.he.enumeration.Sex NONE;可以知道,这里利用了多态性,在外部访问NONE时,只能访问Sex中存在的方法

 其实测试一下可以发现,不需要将方法声明为abstract方法也可以访问,但是使用abstract有更好的强制性,让子类必须重写这个方法


从上面的众多结果可以发现,Enum中的每个属性都是 该类(A)的实例/该类的子类(B extends A)的实例

向Enum类(A)中的属性中添加方法或属性,该类(A)就不会被(abstract或者正常)声明为final,并且产生继承自该类的子类(B extends A),而该属性就会成为子类(B)的对象.

好吧有点绕口......不会说......

如果这个浅析有错误,希望大家指正