在最新的JEP上顯示,Java枚舉將增強泛型支持,並能將方法添加到單個項目上去。這兩個功能可以通過一次更改進行交付,原因是它們捆綁在了一起。更改僅僅會影響到Java編譯器,因此不需要運行時更改。雖然沒有目標版本,但可能會在Java 10中呈現更改。
一開始這個更改沒有得到很大的肯定,比如傑出的Java Champions Joshua Bloch就其實用性提出了質疑。然而,通過進一步的討論和新用例的介紹幫助它逐步獲得了支持。
以防你沒有看到我對@BrianGoetz的回應,我已經看到了JEP列出的介紹,我也撤回了我先前對這個變更的不看好觀點。用例:https://t.co/O1tJO8oSCp
——Joshua Bloch (@joshbloch) 2016年12月7日
讓我們一起通過JEP中舉出的用例和一些其他討論來總結一下這次變更給開發者帶來了什麼改變。Java Champion Lukas Eder提出了一個StackOverflow的問題,介紹了通過配置文件、web會話或類似類型安全的方式檢索和設置屬性的用例。帶有泛型支持的枚舉讓我們可以指示一組可用的鍵和它們相關聯的類型:
public enum Key<T> {
HOST<String>,
PORT<Integer>,
SCORE<Double>
}
public interface PropertiesStore {
public <T> void put(Key<T> key, T value);
public <T> T get(Key<T> key);
}
現在,這些鍵可以安全地在屬性存儲中進行檢索和存儲,因為下面的表達式將無法編譯:
put(PORT, “not a number”); // error, type mismatch: PORT is Key<Integer>
// “not a number” is String
另一方面,允許單個項目有自己的方法可以幫助定義只適用於某些屬性的操作。根據JEP 301所述,上述定義可以擴展如下:
public enum Key<T> {
HOST<String>,
PORT<Integer>,
SCORE<Double> {
double normalise(double x) {
// score normalisation logic
return result;
}
}
}
根據當前的枚舉,所有項目都有通用類型Key,這意味著方法normalise將不可見。但是在這項工作完成後,編譯器將會保留這類型信息,這代表著以下的將為真:
SCORE.normalise(5.37); // compiles
HOST.normalise(5.37); // error: neither HOST nor Key have normalise
要實現這一點,需要改變計算各個枚舉項目的靜態類型的方式。正如讀者可能知道的一樣,枚舉在Java 5中僅僅作為純粹的語法上的甜頭而添加:JVM對枚舉沒有任何特殊的處理,而是由編譯器將枚舉轉換為帶有靜態對象的普通類,然後將其編譯為字節碼。拋開一切技術方面的問題,下面的枚舉:
public enum Colour {
RED, GREEN, BLUE
}
由編譯器粗糙地進行了轉換,如下(這不是一個非常准確的表達,但是足以解釋清楚):
public class Colour extends Enum {
public static final Colour RED = new Colour();
public static final Colour GREEN = new Colour();
public static final Colour BLUE = new Colour();
private Colour() {}
}
由於所有項目的類型是Colour,任何項目特定的方法和類型信息都會丟失。JEP 301要做的是確定使用通用枚舉類型不足以表示單個項目的情況,在這種情況下生產更多更具體的類型,如Colour$RED
、Colour$GREEN
和Colour$BLUE
。
增強的枚舉甚至可以從JDK其他部分正在進行的工作中受益。一方面,局部變量類型推斷可以讓開發人員獲得由編譯器創建的更清晰的類型,即使這些類型的確切形式在編寫代碼的時候是未知的,這意味著上面的代碼可能是以下這樣的:
var s = Key.SCORE; // type of s derived as Key$SCORE
s.normalise(8.29); // method normalise can be accessed
另一方面,一些證據和用例都表示枚舉中的泛型可能更加廣泛地使用於原始類型,這是相當低效的(JVM必須為每個原始類型使用裝盒後對應類型)。這可以通過Valhalla項目中處理原始類型的泛型這個部分消除障礙,並使其可用於大規模使用。
查看英文原文:Java Enums to Be Enhanced with Sharper Type Support