类、枚举与接口
接口,枚举,抽象类(都是由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)