12
回答
Java Enum 类 的 values()方法 api没有,实例是怎么调用的?

java api enum 方法 values 没有 ,我查找了一下,发现 

java.lang.Object extended by java.lang.Enum<ElementType> extended by java.lang.annotation.ElementType
这个类下有
static ElementType[] values() 
          Returns an array containing the constants of this enum type, in the order they are declared.

新手上路,请教一下大家。

我定义了一个  Season 枚举类,为什么可以直接 Season.values() 来返回 这个枚举类内容的数组?annotation 有什么特别的地方么? 


举报
Hassan
发帖于6年前 12回/8K+阅
共有12个答案 最后回答: 6年前

这个方法实际是编译器自动生成的。Java枚举语法只是个语法糖,它的实现需要编译器的参与。

JLS(Java语言规范) 8.9:

如果E是枚举类型的名称,则该类型具有下列隐式声明的静态方法:

public static E[] values();
public static E valueOf(String name);


--- 共有 1 条评论 ---
Hassan哦, 谢谢。我上网查了很久。找到一些说法和你差不多。谢谢。o(∩_∩)o 6年前 回复

引用来自“canghailan”的答案

这个方法实际是编译器自动生成的。Java枚举语法只是个语法糖,它的实现需要编译器的参与。

JLS(Java语言规范) 8.9:

如果E是枚举类型的名称,则该类型具有下列隐式声明的静态方法:

public static E[] values();
public static E valueOf(String name);


我比较倾向于一楼说的,编译器自动生成的方法?类文件中没有这个方法,再自动生成,运行时也不会找到方法啊。
--- 共有 1 条评论 ---
canghailan都自动生成了,字节码里就有这个方法,运行时怎么会找不到呢?其实你自己试试就知道了。 6年前 回复

同2楼,编译时编译器添加的。

public enum TestEnum{
    A, B, C
}
编译后使用javap查看:

Compiled from "TestEnum.java"

public final class TestEnum extends java.lang.Enum{
    public static final TestEnum A;
    public static final TestEnum B;
    public static final TestEnum C;
    public static TestEnum[] values();
    public static TestEnum valueOf(java.lang.String);
    static {};
}

--- 共有 2 条评论 ---
Jeky回复 @canghailan : 手快没用 你的比较细致 6年前 回复
canghailan看来都喜欢枚举A,B,C,还是老兄你手快啊。这编辑器编辑代码老出问题,弄了好几分钟才搞定。。 6年前 回复

引用来自“canghailan”的答案

这个方法实际是编译器自动生成的。Java枚举语法只是个语法糖,它的实现需要编译器的参与。

JLS(Java语言规范) 8.9:

如果E是枚举类型的名称,则该类型具有下列隐式声明的静态方法:

public static E[] values();
public static E valueOf(String name);


我同意这个答案,其实这个问题可以在《java编程思想》一书里面的枚举部分找到答案。

做个实验就能清楚地看到。

源文件:

package test;

public enum EnumTest {
	A, B, C
}

可以看看它的字节码(javap -v EnumTest.class > EnumTest.bytecode):

public final class test.EnumTest extends java.lang.Enum<test.EnumTest>
  SourceFile: "EnumTest.java"
  Signature: #49                          // Ljava/lang/Enum<Ltest/EnumTest;>;
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM

Constant pool:
   #1 = Class              #2             //  test/EnumTest
   #2 = Utf8               test/EnumTest
   #3 = Class              #4             //  java/lang/Enum
   #4 = Utf8               java/lang/Enum
   #5 = Utf8               A
   #6 = Utf8               Ltest/EnumTest;
   #7 = Utf8               B
   #8 = Utf8               C
   #9 = Utf8               ENUM$VALUES
  #10 = Utf8               [Ltest/EnumTest;
  #11 = Utf8               <clinit>
  #12 = Utf8               ()V
  #13 = Utf8               Code
  #14 = String             #5             //  A
  #15 = Methodref          #1.#16         //  test/EnumTest."<init>":(Ljava/lang/String;I)V
  #16 = NameAndType        #17:#18        //  "<init>":(Ljava/lang/String;I)V
  #17 = Utf8               <init>
  #18 = Utf8               (Ljava/lang/String;I)V
  #19 = Fieldref           #1.#20         //  test/EnumTest.A:Ltest/EnumTest;
  #20 = NameAndType        #5:#6          //  A:Ltest/EnumTest;
  #21 = String             #7             //  B
  #22 = Fieldref           #1.#23         //  test/EnumTest.B:Ltest/EnumTest;
  #23 = NameAndType        #7:#6          //  B:Ltest/EnumTest;
  #24 = String             #8             //  C
  #25 = Fieldref           #1.#26         //  test/EnumTest.C:Ltest/EnumTest;
  #26 = NameAndType        #8:#6          //  C:Ltest/EnumTest;
  #27 = Fieldref           #1.#28         //  test/EnumTest.ENUM$VALUES:[Ltest/EnumTest;
  #28 = NameAndType        #9:#10         //  ENUM$VALUES:[Ltest/EnumTest;
  #29 = Utf8               LineNumberTable
  #30 = Utf8               LocalVariableTable
  #31 = Methodref          #3.#16         //  java/lang/Enum."<init>":(Ljava/lang/String;I)V
  #32 = Utf8               this
  #33 = Utf8               values
  #34 = Utf8               ()[Ltest/EnumTest;
  #35 = Methodref          #36.#38        //  java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
  #36 = Class              #37            //  java/lang/System
  #37 = Utf8               java/lang/System
  #38 = NameAndType        #39:#40        //  arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
  #39 = Utf8               arraycopy
  #40 = Utf8               (Ljava/lang/Object;ILjava/lang/Object;II)V
  #41 = Utf8               valueOf
  #42 = Utf8               (Ljava/lang/String;)Ltest/EnumTest;
  #43 = Methodref          #3.#44         //  java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #44 = NameAndType        #41:#45        //  valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #45 = Utf8               (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
  #46 = Utf8               SourceFile
  #47 = Utf8               EnumTest.java
  #48 = Utf8               Signature
  #49 = Utf8               Ljava/lang/Enum<Ltest/EnumTest;>;
{
  public static final test.EnumTest A;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM


  public static final test.EnumTest B;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM


  public static final test.EnumTest C;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM


  static {};
    flags: ACC_STATIC

    Code:
      stack=4, locals=0, args_size=0
         0: new           #1                  // class test/EnumTest
         3: dup           
         4: ldc           #14                 // String A
         6: iconst_0      
         7: invokespecial #15                 // Method "<init>":(Ljava/lang/String;I)V
        10: putstatic     #19                 // Field A:Ltest/EnumTest;
        13: new           #1                  // class test/EnumTest
        16: dup           
        17: ldc           #21                 // String B
        19: iconst_1      
        20: invokespecial #15                 // Method "<init>":(Ljava/lang/String;I)V
        23: putstatic     #22                 // Field B:Ltest/EnumTest;
        26: new           #1                  // class test/EnumTest
        29: dup           
        30: ldc           #24                 // String C
        32: iconst_2      
        33: invokespecial #15                 // Method "<init>":(Ljava/lang/String;I)V
        36: putstatic     #25                 // Field C:Ltest/EnumTest;
        39: iconst_3      
        40: anewarray     #1                  // class test/EnumTest
        43: dup           
        44: iconst_0      
        45: getstatic     #19                 // Field A:Ltest/EnumTest;
        48: aastore       
        49: dup           
        50: iconst_1      
        51: getstatic     #22                 // Field B:Ltest/EnumTest;
        54: aastore       
        55: dup           
        56: iconst_2      
        57: getstatic     #25                 // Field C:Ltest/EnumTest;
        60: aastore       
        61: putstatic     #27                 // Field ENUM$VALUES:[Ltest/EnumTest;
        64: return        
      LineNumberTable:
        line 4: 0
        line 3: 39
      LocalVariableTable:
        Start  Length  Slot  Name   Signature

  public static test.EnumTest[] values();
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=5, locals=3, args_size=0
         0: getstatic     #27                 // Field ENUM$VALUES:[Ltest/EnumTest;
         3: dup           
         4: astore_0      
         5: iconst_0      
         6: aload_0       
         7: arraylength   
         8: dup           
         9: istore_1      
        10: anewarray     #1                  // class test/EnumTest
        13: dup           
        14: astore_2      
        15: iconst_0      
        16: iload_1       
        17: invokestatic  #35                 // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
        20: aload_2       
        21: areturn       
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature

  public static test.EnumTest valueOf(java.lang.String);
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=2, locals=1, args_size=1
         0: ldc           #1                  // class test/EnumTest
         2: aload_0       
         3: invokestatic  #43                 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
         6: checkcast     #1                  // class test/EnumTest
         9: areturn       
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
}
从字节码可以看出一下几点:
1.它是Enum的子类。

public final class test.EnumTest extends java.lang.Enum<test.EnumTest>

2.枚举常量是以public static final类常量的形式实现的。

public static final test.EnumTest A;
public static final test.EnumTest B;
public static final test.EnumTest C;
3.编译器自动生成了values和valueOf方法。 

public static test.EnumTest[] values();
public static test.EnumTest valueOf(java.lang.String);


@loki_lan

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

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

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

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

--- 共有 3 条评论 ---
Hassan谢谢。学习了。 6年前 回复
loki_lanpublic enum ElementType extends Enum<ElementType>查API看到了,之前那个API没有这个,害人,学习了。 6年前 回复
loki_lan你说对了 6年前 回复

引用来自“JekyCui”的答案

@loki_lan

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

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

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

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

下面是官方解答:

引子: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared. 

翻译啥的我想就不必了

--- 共有 1 条评论 ---
loki_lan查API是可以直接看到valuesOf(),但是没有values()这个方法的,所以肯定是在编译的时候自动生成了,哈哈,又学到了,:) 6年前 回复
顶部