从哪里来的Enum.values()?

时间:2010-10-06 19:36:14

标签: java android enums

我正在浏览文档和源代码,因为我想确定values()总是按照声明枚举值的顺序返回一个数组。事实证明,据我所知,它不是in the documentation

我检查了Enum类的源代码,但没有运气(there is a related, private "getValues" method)。

所以我猜测一些编译器/解释器-foo已经开始创建一个扩展Enum的类,如下所示:

public static enum MyEnum

在编译期间,values()也被静态转换为硬编码数组吗?或者它实际上是在运行时调用的方法,如果是,它在哪里定义?

4 个答案:

答案 0 :(得分:13)

values()方法是enum类型定义的一部分。不要与Enum基类混淆。正式定义在Section 8.9 of the JLS中,它确实指定返回的顺序与它们的声明顺序相匹配。

答案 1 :(得分:2)

从下面通过反汇编枚举获得的字节码可以看出,枚举上的values()方法只返回包含所有声明的枚举常量的private static数组的副本。此数组ENUM$VALUES填入静态初始化块。

DaysOfTheWeek.java

public enum DaysOfTheWeek {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

DaysOfTheWeek.java反汇编

在静态块之后,标记为0-92的字节码初始化枚举常量,标记为94-139的字节码将这些常量放入数组中,标记为140的字节码将数组分配给ENUM$VALUES静态字段。类。 values()方法中的代码只需通过调用ENUM$VALUES来创建分配给System.arraycopy字段的数组的副本,然后返回副本。

Compiled from "DaysOfTheWeek.java"
public final class DaysOfTheWeek extends java.lang.Enum{
public static final DaysOfTheWeek MONDAY;

public static final DaysOfTheWeek TUESDAY;

public static final DaysOfTheWeek WEDNESDAY;

public static final DaysOfTheWeek THURSDAY;

public static final DaysOfTheWeek FRIDAY;

public static final DaysOfTheWeek SATURDAY;

public static final DaysOfTheWeek SUNDAY;

static {};
  Code:
   0:   new #1; //class DaysOfTheWeek
   3:   dup
   4:   ldc #18; //String MONDAY
   6:   iconst_0
   7:   invokespecial   #19; //Method "<init>":(Ljava/lang/String;I)V
   10:  putstatic   #23; //Field MONDAY:LDaysOfTheWeek;
   13:  new #1; //class DaysOfTheWeek
   16:  dup
   17:  ldc #25; //String TUESDAY
   19:  iconst_1
   20:  invokespecial   #19; //Method "<init>":(Ljava/lang/String;I)V
   23:  putstatic   #26; //Field TUESDAY:LDaysOfTheWeek;
   26:  new #1; //class DaysOfTheWeek
   29:  dup
   30:  ldc #28; //String WEDNESDAY
   32:  iconst_2
   33:  invokespecial   #19; //Method "<init>":(Ljava/lang/String;I)V
   36:  putstatic   #29; //Field WEDNESDAY:LDaysOfTheWeek;
   39:  new #1; //class DaysOfTheWeek
   42:  dup
   43:  ldc #31; //String THURSDAY
   45:  iconst_3
   46:  invokespecial   #19; //Method "<init>":(Ljava/lang/String;I)V
   49:  putstatic   #32; //Field THURSDAY:LDaysOfTheWeek;
   52:  new #1; //class DaysOfTheWeek
   55:  dup
   56:  ldc #34; //String FRIDAY
   58:  iconst_4
   59:  invokespecial   #19; //Method "<init>":(Ljava/lang/String;I)V
   62:  putstatic   #35; //Field FRIDAY:LDaysOfTheWeek;
   65:  new #1; //class DaysOfTheWeek
   68:  dup
   69:  ldc #37; //String SATURDAY
   71:  iconst_5
   72:  invokespecial   #19; //Method "<init>":(Ljava/lang/String;I)V
   75:  putstatic   #38; //Field SATURDAY:LDaysOfTheWeek;
   78:  new #1; //class DaysOfTheWeek
   81:  dup
   82:  ldc #40; //String SUNDAY
   84:  bipush  6
   86:  invokespecial   #19; //Method "<init>":(Ljava/lang/String;I)V
   89:  putstatic   #41; //Field SUNDAY:LDaysOfTheWeek;
   92:  bipush  7
   94:  anewarray   #1; //class DaysOfTheWeek
   97:  dup
   98:  iconst_0
   99:  getstatic   #23; //Field MONDAY:LDaysOfTheWeek;
   102: aastore
   103: dup
   104: iconst_1
   105: getstatic   #26; //Field TUESDAY:LDaysOfTheWeek;
   108: aastore
   109: dup
   110: iconst_2
   111: getstatic   #29; //Field WEDNESDAY:LDaysOfTheWeek;
   114: aastore
   115: dup
   116: iconst_3
   117: getstatic   #32; //Field THURSDAY:LDaysOfTheWeek;
   120: aastore
   121: dup
   122: iconst_4
   123: getstatic   #35; //Field FRIDAY:LDaysOfTheWeek;
   126: aastore
   127: dup
   128: iconst_5
   129: getstatic   #38; //Field SATURDAY:LDaysOfTheWeek;
   132: aastore
   133: dup
   134: bipush  6
   136: getstatic   #41; //Field SUNDAY:LDaysOfTheWeek;
   139: aastore
   140: putstatic   #43; //Field ENUM$VALUES:[LDaysOfTheWeek;
   143: return

public static DaysOfTheWeek[] values();
  Code:
   0:   getstatic   #43; //Field ENUM$VALUES:[LDaysOfTheWeek;
   3:   dup
   4:   astore_0
   5:   iconst_0
   6:   aload_0
   7:   arraylength
   8:   dup
   9:   istore_1
   10:  anewarray   #1; //class DaysOfTheWeek
   13:  dup
   14:  astore_2
   15:  iconst_0
   16:  iload_1
   17:  invokestatic    #51; //Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
   20:  aload_2
   21:  areturn

public static DaysOfTheWeek valueOf(java.lang.String);
  Code:
   0:   ldc #1; //class DaysOfTheWeek
   2:   aload_0
   3:   invokestatic    #59; //Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
   6:   checkcast   #1; //class DaysOfTheWeek
   9:   areturn

}

答案 2 :(得分:1)

您提供的链接(其中有私有getValues方法)来自Apache Harmony(版本6,这是一个开源Java SE)。它们与Oracle的Enum类(没有私有getValues方法)有不同的实现。

Oracle java(撰写本文时版本1.6.0-21)具有valueOf(Class<T> enumType, String name)。这是它的实现:

 /**
     * Returns the enum constant of the specified enum type with the
     * specified name.  The name must match exactly an identifier used
     * to declare an enum constant in this type.  (Extraneous whitespace
     * characters are not permitted.) 
     *
     * @param enumType the <tt>Class</tt> object of the enum type from which
     *      to return a constant
     * @param name the name of the constant to return
     * @return the enum constant of the specified enum type with the
     *      specified name
     * @throws IllegalArgumentException if the specified enum type has
     *         no constant with the specified name, or the specified
     *         class object does not represent an enum type
     * @throws NullPointerException if <tt>enumType</tt> or <tt>name</tt>
     *         is null
     * @since 1.5
     */
    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum const " + enumType +"." + name);
    }

从本质上讲,Apache实现了valueOf的不同之处。


Enum(或enum)有一个名为values()的公共静态方法,它返回enum内声明的枚举值常量。这是由编译器填充的。

答案 3 :(得分:1)

我将添加到Devon的答案中,根据定义,编译器会添加values()方法。
来自枚举tutorial

  

编译器自动添加一些   创建一个特殊的方法   枚举。例如,他们有静态   values方法,返回一个数组   包含所有的值   按照声明的顺序枚举。