java enum values_Java中Enum类下的values()方法的由来

有如下Enum类:

public enum Test{

A,B,C

}

该类下有values()方法,但查API可知道java.lang.Enum下根本没有这个方法,该方法在java.lang.annotation.ElementType类下(public enum ElementType extendsEnum),我们先看看编译后,用javap命令查看编译后的内容:

C:\>javap Test

Compiled from "Test.java"

public final class Test extends java.lang.Enum<Test> {

public static final Test A;

public static final Test B;

public static final Test C;

public static Test[] values();

public static Test valueOf(java.lang.String);

static {};

}

可以看出,貌似编译后Test是实现了java.lang.annotation.ElementType这个接口,再看其字节码:

C:\>javap -v Test

Classfile /C:/Test.class

Last modified 2012-11-22; size 782 bytes

MD5 checksum 17335f37d5ac9d7fe7d5544782cf7088

Compiled from "Test.java"

public final class Test extends java.lang.Enum

Signature: #32                          // Ljava/lang/Enum;

SourceFile: "Test.java"

minor version: 0

major version: 51

flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM

Constant pool:

#1 = Fieldref           #4.#35         //  Test.$VALUES:[LTest;

#2 = Methodref          #36.#37        //  "[LTest;".clone:()Ljava/lang/Objec

t;

#3 = Class              #20            //  "[LTest;"

#4 = Class              #38            //  Test

#5 = Methodref          #14.#39        //  java/lang/Enum.valueOf:(Ljava/lang

/Class;Ljava/lang/String;)Ljava/lang/Enum;

#6 = Methodref          #14.#40        //  java/lang/Enum."":(Ljava/lan

g/String;I)V

#7 = String             #15            //  A

#8 = Methodref          #4.#41         //  Test."":(Ljava/lang/String;I

)V

#9 = Fieldref           #4.#42         //  Test.A:LTest;

#10 = String             #17            //  B

#11 = Fieldref           #4.#43         //  Test.B:LTest;

#12 = String             #18            //  C

#13 = Fieldref           #4.#44         //  Test.C:LTest;

#14 = Class              #45            //  java/lang/Enum

#15 = Utf8               A

#16 = Utf8               LTest;

#17 = Utf8               B

#18 = Utf8               C

#19 = Utf8               $VALUES

#20 = Utf8               [LTest;

#21 = Utf8               values

#22 = Utf8               ()[LTest;

#23 = Utf8               Code

#24 = Utf8               LineNumberTable

#25 = Utf8               valueOf

#26 = Utf8               (Ljava/lang/String;)LTest;

#27 = Utf8

#28 = Utf8               (Ljava/lang/String;I)V

#29 = Utf8               Signature

#30 = Utf8               ()V

#31 = Utf8

#32 = Utf8               Ljava/lang/Enum;

#33 = Utf8               SourceFile

#34 = Utf8               Test.java

#35 = NameAndType        #19:#20        //  $VALUES:[LTest;

#36 = Class              #20            //  "[LTest;"

#37 = NameAndType        #46:#47        //  clone:()Ljava/lang/Object;

#38 = Utf8               Test

#39 = NameAndType        #25:#48        //  valueOf:(Ljava/lang/Class;Ljava/la

ng/String;)Ljava/lang/Enum;

#40 = NameAndType        #27:#28        //  "":(Ljava/lang/String;I)V

#41 = NameAndType        #27:#28        //  "":(Ljava/lang/String;I)V

#42 = NameAndType        #15:#16        //  A:LTest;

#43 = NameAndType        #17:#16        //  B:LTest;

#44 = NameAndType        #18:#16        //  C:LTest;

#45 = Utf8               java/lang/Enum

#46 = Utf8               clone

#47 = Utf8               ()Ljava/lang/Object;

#48 = Utf8               (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;

{

public static final Test A;

flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

public static final Test B;

flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

public static final Test C;

flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM

public static Test[] values();

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=1, locals=0, args_size=0

0: getstatic     #1                  // Field $VALUES:[LTest;

3: invokevirtual #2                  // Method "[LTest;".clone:()Ljava/

lang/Object;

6: checkcast     #3                  // class "[LTest;"

9: areturn

LineNumberTable:

line 1: 0

public static Test valueOf(java.lang.String);

flags: ACC_PUBLIC, ACC_STATIC

Code:

stack=2, locals=1, args_size=1

0: ldc_w         #4                  // class Test

3: aload_0

4: invokestatic  #5                  // Method java/lang/Enum.valueOf:(

Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;

7: checkcast     #4                  // class Test

10: areturn

LineNumberTable:

line 1: 0

static {};

flags: ACC_STATIC

Code:

stack=4, locals=0, args_size=0

0: new           #4                  // class Test

3: dup

4: ldc           #7                  // String A

6: iconst_0

7: invokespecial #8                  // Method "":(Ljava/lang/Str

ing;I)V

10: putstatic     #9                  // Field A:LTest;

13: new           #4                  // class Test

16: dup

17: ldc           #10                 // String B

19: iconst_1

20: invokespecial #8                  // Method "":(Ljava/lang/Str

ing;I)V

23: putstatic     #11                 // Field B:LTest;

26: new           #4                  // class Test

29: dup

30: ldc           #12                 // String C

32: iconst_2

33: invokespecial #8                  // Method "":(Ljava/lang/Str

ing;I)V

36: putstatic     #13                 // Field C:LTest;

39: iconst_3

40: anewarray     #4                  // class Test

43: dup

44: iconst_0

45: getstatic     #9                  // Field A:LTest;

48: aastore

49: dup

50: iconst_1

51: getstatic     #11                 // Field B:LTest;

54: aastore

55: dup

56: iconst_2

57: getstatic     #13                 // Field C:LTest;

60: aastore

61: putstatic     #1                  // Field $VALUES:[LTest;

64: return

LineNumberTable:

line 2: 0

line 1: 39

}

结论如下:

1、java.lang.Enum,而编译后是public final class Test extends java.lang.Enum推不出Test是ElementType的子类这个结果。如果想导出这个结果,应该是Enum extends ElementType>。

这里Test和ElementType一点关系都没有。而恰恰相反,Enum的声明是:Enum extends Enum>,即后面这个泛型里必须是Enum子类。所以合理的推理是这样的:Test是Enum的子类,ElementType也是Enum的子类。

2、为什么ElementType会有values()和valueOf()方法,这不是刚好,是因为ElementType本身也是Enum的子类,编译时自动添加了这些方法。

3、任何类也不可能是ElementType的子类,因为任何enum编译后都是final修饰的,除非它的某个枚举量有class body,而ElementType没有。final修饰的类不可继承。

一句话总结:编译器自动生成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值