繁体   English   中英

从哪里来的Enum.values()?

[英]From whence cometh Enum.values()?

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

我检查了Enum类的源代码,没有运气( 有一个相关的,私有的“getValues”方法 )。

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

public static enum MyEnum

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

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

从下面通过反汇编枚举获得的字节码可以看出,枚举上的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()方法中的代码只是通过调用System.arraycopy来创建分配给ENUM$VALUES字段的数组的副本,并返回该副本。

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

}

您提供的链接(其中有私有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 这是由编译器填充的。

我将添加到Devon的答案中,根据定义,编辑器会添加values()方法。
从enums 教程

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM