2010-10-06 17 views
8

Tôi đã xem qua tài liệu và mã nguồn, vì tôi muốn chắc chắn rằng các giá trị() sẽ luôn trả về một mảng theo thứ tự trong đó các giá trị Enum được khai báo. Hóa ra, nó không phải là in the documentation theo như tôi có thể nói.Từ whence cometh Enum.values ​​()?

Tôi đã kiểm tra mã nguồn cho lớp Enum và không có may mắn (there is a related, private "getValues" method).

Vì vậy, tôi đoán rằng một số trình biên dịch/phiên dịch-foo đã xảy ra để tạo ra một lớp mà kéo dài Enum ra khỏi một khai báo như sau:

public static enum MyEnum 

Vậy là giá trị() cũng tĩnh dịch sang một mảng hardcoded trong quá trình biên dịch? Hoặc là nó thực sự là một phương pháp gọi là lúc chạy, và nếu như vậy, nó được định nghĩa ở đâu?

+0

Nếu bạn quan tâm nhiều, điều đó có thể có nghĩa là một cái gì đó sẽ bị hỏng nếu trong tuyên bố enum của bạn bạn di chuyển công cụ xung quanh. Điều đó thật sự rất mỏng manh. Vì vậy, tôi muốn nói nếu bạn quan tâm, bạn có thể có một thiết kế kỳ lạ. Tại sao nó quan trọng với bạn rằng họ đang theo thứ tự? –

+0

+1 Chỉ dành cho tiêu đề. – Zoe

+0

@Mark Peters - Bởi vì tôi đang sử dụng enums cho các mục menu được sắp xếp ở nhiều nơi. Chắc chắn, tôi có thể tạo ra một số loại chức năng đặt hàng trả lại chúng theo thứ tự nào đó ... nhưng tại sao? Nó sẽ không phá vỡ nếu tôi di chuyển chúng, nó sẽ chỉ thay đổi thứ tự chúng được trình bày trong ứng dụng. – DougW

Trả lời

13

Phương thức values() là một phần của định nghĩa loại enum. Không được nhầm lẫn với lớp cơ sở Enum. Định nghĩa chính thức là trong các Section 8.9 of the JLS mà không chỉ định thứ tự trả lại phù hợp với thứ tự mà chúng được khai báo.

+0

+1 cho thông số kỹ thuật! –

+0

Tuyệt vời, đó là những gì tôi cho là đang diễn ra. Cảm ơn! – DougW

1

Liên kết của bạn mà bạn đã cung cấp (trong đó có phương thức riêng getValues) là từ Apache Harmony (phiên bản 6, là mã nguồn mở Java SE). Họ có một triển khai khác với lớp Enum của Oracle (không có phương thức riêng tư getValues).

Java java (phiên bản 1.6.0-21 tại thời điểm viết) có valueOf(Class<T> enumType, String name). Dưới đây là cách triển khai:

/** 
    * 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); 
    } 

Về bản chất, đó là cách Apache triển khai valueOf khác nhau.


Enum (hoặc enum) có một phương pháp tĩnh công cộng gọi values() mà trả về giá trị hằng liệt kê khai báo trong enum. Đó là dân cư của trình biên dịch.

+2

* Shiver * Tôi vẫn bị cuốn hút bằng cách nhìn thấy "lớp Enum của Oracle" hoặc "Java Java". Làm cho tôi nghĩ rằng bạn đang nói về JVM mà họ tạo ra để sử dụng trong cơ sở dữ liệu Oracle. –

+0

giữ tên thay đổi cho đến khi Oracle đã thực sự làm một cái gì đó lớn cho java. – irreputable

+0

LOL .... nếu bạn không để ý đến kẻ khác, hầu hết các trang web 'sun.com' hiện là 'oracle.com'. Cũng có thể áp dụng quá .... –

2

Như bạn có thể thấy từ mã byte bên dưới thu được bằng cách ngắt tách một enum, phương thức values() trên enums đơn giản trả về một bản sao của mảng private static chứa tất cả hằng số enum được khai báo. Mảng ENUM$VALUES này được điền vào một khối khởi tạo tĩnh.

DaysOfTheWeek.java

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

DaysOfTheWeek.java tháo rời

Sau khi khối tĩnh, các bytecode đánh dấu 0-92 khởi tạo các hằng enum, các bytecode đánh dấu 94-139 đặt những hằng số trong một mảng và bytecode đánh dấu 140 gán mảng vào trường tĩnh ENUM$VALUES của lớp. Mã trong phương thức values() chỉ cần tạo bản sao của mảng được gán cho trường ENUM$VALUES bằng cách gọi System.arraycopy trên đó và trả về bản sao.

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 

} 
+0

+1 để chứng minh điều đó một cách khó khăn;). Cảm ơn. – DougW

1

Tôi sẽ thêm vào câu trả lời của Devon, phương pháp values() được trình biên dịch thêm vào, theo định nghĩa.
Từ enums tutorial:

Trình biên dịch sẽ tự động thêm một số phương pháp đặc biệt khi nó tạo ra một enum . Ví dụ: chúng có phương thức giá trị tĩnh trả về một mảng chứa tất cả các giá trị của enum theo thứ tự chúng được khai báo.

Các vấn đề liên quan