[英]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.