簡體   English   中英

如何為Java 6枚舉實現values()?

[英]How is values() implemented for Java 6 enums?

在Java中,您可以按如下方式創建枚舉:

public enum Letter {
    A, B, C, D, E, F, G;

    static {
       for(Letter letter : values()) {
          // do something with letter
       }
    }
}

這個問題涉及“values()”方法。 具體來說,它是如何實現的? 通常,我可以在Eclipse中使用F3或CTRL + Click跳轉到Java類的源代碼(即使對於String,Character,Integer甚至Enum這樣的類)。 可以查看其他枚舉方法的來源(例如,valueOf(String))。

“values()”每次調用時都會創建一個新數組嗎? 如果我將它分配給局部變量然后修改其中一個元素,會發生什么(顯然這不會影響values()返回的值,這意味着每次都會分配一個新數組)。

它的代碼是原生的嗎? 或者JVM /編譯器是否專門處理它,只有當它無法證明它不會被修改時才從values()返回一個新實例。

基本上,編譯器(javac)將您的枚舉轉換為包含編譯時所有值的靜態數組。 當您調用values()時,它會為您提供此數組的.clone'd()副本。

鑒於這個簡單的枚舉:

public enum Stuff {
   COW, POTATO, MOUSE;
}

您實際上可以查看Java生成的代碼:

public enum Stuff extends Enum<Stuff> {
    /*public static final*/ COW /* = new Stuff("COW", 0) */,
    /*public static final*/ POTATO /* = new Stuff("POTATO", 1) */,
    /*public static final*/ MOUSE /* = new Stuff("MOUSE", 2) */;
    /*synthetic*/ private static final Stuff[] $VALUES = new Stuff[]{Stuff.COW, Stuff.POTATO, Stuff.MOUSE};

    public static Stuff[] values() {
        return (Stuff[])$VALUES.clone();
    }

    public static Stuff valueOf(String name) {
        return (Stuff)Enum.valueOf(Stuff.class, name);
    }

    private Stuff(/*synthetic*/ String $enum$name, /*synthetic*/ int $enum$ordinal) {
        super($enum$name, $enum$ordinal);
    }
}

您可以通過創建臨時目錄並運行來查看javac如何“翻譯”您的類:

javac -d <output directory> -XD-printflat filename.java

如果將其分配給局部變量,則可以修改的唯一內容是為此變量分配另一個枚舉。 這不會改變枚舉本身,因為您只是更改變量引用的對象。

似乎枚舉實際上是單例,因此每個枚舉中只有一個元素可以存在於整個程序中,這使得==運算符對於枚舉是合法的。

因此沒有性能問題,您不能在枚舉定義中意外更改某些內容。

它的代碼是原生的嗎? 或者JVM /編譯器是否專門處理它,只有當它無法證明它不會被修改時才從values()返回一個新實例。

1)否。或者至少在當前的實現中不是。 請參閱@ lucasmo的證據答案。

2)AFAIK,沒有。

假設它可以做到這一點。 然而,證明從不在本地修改數組對於JIT來說將是復雜且相對昂貴的。 如果數組從調用values()的方法“逃逸”,它會變得更復雜,更昂貴。

很可能這個(假設的)優化不會得到回報...當對所有Java代碼進行平均時。

另一個問題是這種(假設的)優化可能會打開安全漏洞。


有趣的是,JLS似乎沒有指定values()成員返回數組副本。 常識1說它必須做......但實際上沒有明確說明。

1 - 如果values()返回一個共享(可變) enum值數組,那將是一個巨大的安全漏洞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM