类枚举与接口

Posted 渊源谭

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类枚举与接口相关的知识,希望对你有一定的参考价值。

接口,枚举,抽象类(都是由class变过来的)
enum反编译过来就是class或abstract class


定义接口的原因:
当初些抽象类的时候(假设抽象类中一个普通的属性都没有,全是由
public static final修饰的 所有的方法都是抽象方法,都由public abstract修饰)
人们不愿意写这么多关键字,所以定义了一个新的关键字interface,所有关键字省略
特殊的抽象类就变成接口

enum可以拿抽象类来写(枚举是某种类型的取值是若干有限集合中的一个)
其中转变的过程为:
限制class Gender{}的取值(实例对象)只有一个所以写成

class Gender{
    private Gender(){}
    private static Gender g = new Gender();
    static public void getInstance(){
        return g;
    }
}

但不够方便,所以改为

class Gender{
    private Gender(){}
    public static Gender g = new Gender();
    
}

但因为是类变量,而且值还可以改,值被所有人共享,万一改成null,
就再也获取不到Gender的实例了,所以改为

class Gender{
    private Gender(){}
    public final static Gender g = new Gender();
    
}

此时Gender的取值只能为g(共享的常量)当有多个时:

class Gender{
    private Gender(){}
    public final static Gender FEMALE1 = new Gender();
    public final static Gender MALE1 = new Gender();
    public final static Gender FEMALE2 = new Gender();
    public final static Gender MALE2 = new Gender();
    
}

此时唯一不同的就是4个变量(且都用类名来调用)为了简化
所以在你构造器没有参数的时候就可以写成

enum Gender{
    FEMALE1,MALE1,FEMALE2,MALE2
}

所以刚才的类就替换成了枚举
枚举里可以加抽象方法(如果一个类里有抽象方法,那么这个类就是抽象的)

abstract class Gender{
    private Gender(){}
    abstract void test();
    public final static Gender FEMALE1 = new Gender();
    public final static Gender MALE1 = new Gender();
    public final static Gender FEMALE2 = new Gender();
    public final static Gender MALE2 = new Gender();
    
}

此时abstract class 是不能被实例化的
只能使用匿名内部类来生成对象

abstract class Gender{
    private Gender(){}
    abstract void test();
    public final static Gender FEMALE1 = new Gender(){
        public void test(){}
    };
    public final static Gender MALE1 = new Gender(){
        public void test(){}
    };
    public final static Gender FEMALE2 = new Gender(){
        public void test(){}
    };
    public final static Gender MALE2 = new Gender(){
        public void test(){}
    };    
}

而枚举要实现接口要做的操作

enum Gender{
    FEMALE(){
        public void test(){}
    },MALE(){
        public void test(){}
    };
    abstract void test();
}

所以说MALE和FEMALE都是enum的一个实例
用javap -v反编译以下代码:

enum Gender{
    FEMALE(){
        public void test(){}
    },MALE(){
        public void test(){}
    };
    abstract void test();
}

得到的结果为:

Classfile /home/briup/Gender.class
  Last modified 2017-8-24; size 937 bytes
  MD5 checksum 5ada6ef037132305206b15964108ae09
  Compiled from "Test.java"
abstract class Gender extends java.lang.Enum<Gender>
  Signature: #37                          // Ljava/lang/Enum<LGender;>;
  SourceFile: "Test.java"
  InnerClasses:
       static #12; //class Gender$2
       static #8; //class Gender$1
  minor version: 0
  major version: 51
  flags: ACC_SUPER, ACC_ABSTRACT, ACC_ENUM
Constant pool:
   #1 = Methodref          #5.#40         //  Gender."<init>":(Ljava/lang/String;I)V
   #2 = Fieldref           #5.#41         //  Gender.$VALUES:[LGender;
   #3 = Methodref          #42.#43        //  "[LGender;".clone:()Ljava/lang/Object;
   #4 = Class              #23            //  "[LGender;"
   #5 = Class              #44            //  Gender
   #6 = Methodref          #16.#45        //  java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
   #7 = Methodref          #16.#46        //  java/lang/Enum."<init>":(Ljava/lang/String;I)V
   #8 = Class              #47            //  Gender$1
   #9 = String             #19            //  FEMALE
  #10 = Methodref          #8.#40         //  Gender$1."<init>":(Ljava/lang/String;I)V
  #11 = Fieldref           #5.#48         //  Gender.FEMALE:LGender;
  #12 = Class              #49            //  Gender$2
  #13 = String             #21            //  MALE
  #14 = Methodref          #12.#40        //  Gender$2."<init>":(Ljava/lang/String;I)V
  #15 = Fieldref           #5.#50         //  Gender.MALE:LGender;
  #16 = Class              #51            //  java/lang/Enum
  #17 = Utf8               
  #18 = Utf8               InnerClasses
  #19 = Utf8               FEMALE
  #20 = Utf8               LGender;
  #21 = Utf8               MALE
  #22 = Utf8               $VALUES
  #23 = Utf8               [LGender;
  #24 = Utf8               values
  #25 = Utf8               ()[LGender;
  #26 = Utf8               Code
  #27 = Utf8               LineNumberTable
  #28 = Utf8               valueOf
  #29 = Utf8               (Ljava/lang/String;)LGender;
  #30 = Utf8               <init>
  #31 = Utf8               (Ljava/lang/String;I)V
  #32 = Utf8               Signature
  #33 = Utf8               ()V
  #34 = Utf8               test
  #35 = Utf8               (Ljava/lang/String;ILGender$1;)V
  #36 = Utf8               <clinit>
  #37 = Utf8               Ljava/lang/Enum<LGender;>;
  #38 = Utf8               SourceFile
  #39 = Utf8               Test.java
  #40 = NameAndType        #30:#31        //  "<init>":(Ljava/lang/String;I)V
  #41 = NameAndType        #22:#23        //  $VALUES:[LGender;
  #42 = Class              #23            //  "[LGender;"
  #43 = NameAndType        #52:#53        //  clone:()Ljava/lang/Object;
  #44 = Utf8               Gender
  #45 = NameAndType        #28:#54        //  valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #46 = NameAndType        #30:#31        //  "<init>":(Ljava/lang/String;I)V
  #47 = Utf8               Gender$1
  #48 = NameAndType        #19:#20        //  FEMALE:LGender;
  #49 = Utf8               Gender$2
  #50 = NameAndType        #21:#20        //  MALE:LGender;
  #51 = Utf8               java/lang/Enum
  #52 = Utf8               clone
  #53 = Utf8               ()Ljava/lang/Object;
  #54 = Utf8               (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
{
  public static final Gender FEMALE;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static final Gender MALE;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

  public static Gender[] values();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: getstatic     #2                  // Field $VALUES:[LGender;
         3: invokevirtual #3                  // Method "[LGender;".clone:()Ljava/lang/Object;
         6: checkcast     #4                  // class "[LGender;"
         9: areturn       
      LineNumberTable:
        line 1: 0

  public static Gender valueOf(java.lang.String);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=1
         0: ldc_w         #5                  // class Gender
         3: aload_0       
         4: invokestatic  #6                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
         7: checkcast     #5                  // class Gender
        10: areturn       
      LineNumberTable:
        line 1: 0
 public abstract void test();
    flags: ACC_PUBLIC, ACC_ABSTRACT

  Gender(java.lang.String, int, Gender$1);
    flags: ACC_SYNTHETIC
    Code:
      stack=3, locals=4, args_size=4
         0: aload_0       
         1: aload_1       
         2: iload_2       
         3: invokespecial #1                  // Method "<init>":(Ljava/lang/String;I)V
         6: return        
      LineNumberTable:
        line 1: 0

  static {};
    flags: ACC_STATIC
    Code:
      stack=4, locals=0, args_size=0
         0: new           #8                  // class Gender$1
         3: dup           
         4: ldc           #9                  // String FEMALE
         6: iconst_0      
         7: invokespecial #10                 // Method Gender$1."<init>":(Ljava/lang/String;I)V
        10: putstatic     #11                 // Field FEMALE:LGender;
        13: new           #12                 // class Gender$2
        16: dup           
        17: ldc           #13                 // String MALE
        19: iconst_1      
        20: invokespecial #14                 // Method Gender$2."<init>":(Ljava/lang/String;I)V
        23: putstatic     #15                 // Field MALE:LGender;
        26: iconst_2      
        27: anewarray     #5                  // class Gender
        30: dup           
        31: iconst_0      
        32: getstatic     #11                 // Field FEMALE:LGender;
        35: aastore       
        36: dup           
        37: iconst_1      
        38: getstatic     #15                 // Field MALE:LGender;
        41: aastore       
        42: putstatic     #2                  // Field $VALUES:[LGender;
        45: return        
      LineNumberTable:
        line 2: 0
        line 5: 13
        line 1: 26
}

由此可见,java中的接口和枚举都是人们为了简化操作而专门设计的!(其实都是类o(* ̄︶ ̄*)o)

以上是关于类枚举与接口的主要内容,如果未能解决你的问题,请参考以下文章

Java 枚举类的基本使用

java 代码片段

Java枚举类接口实战

学妹问我Java枚举类与注解,我直接用这个搞定她!

学妹问我Java枚举类与注解,我直接用这个搞定她!

枚举类