Java 10新特性解密,引入類型推斷機(jī)制
隨著Java開(kāi)發(fā)工具包(JDK)9的發(fā)布,大量的注意力都集中在Java的最新特性上,包括引入模塊(通過(guò)集成項(xiàng)目Jigsaw)。盡管最近的很多關(guān)注都集中在這些強(qiáng)大的新功能上,但下一個(gè)版本的Java:JDK 10已經(jīng)開(kāi)始準(zhǔn)備了。在本文中,我們將粗略地介紹一下JDK 10的主要特性,并探討JDK 10中可能包含的一些特性。
請(qǐng)注意,本文中所包含的信息在寫(xiě)本文時(shí)是準(zhǔn)確的。但是到發(fā)布時(shí),JDK 10特性組預(yù)計(jì)將會(huì)增加。
新功能
與之前的JDK版本一樣,對(duì)于即將到來(lái)的JDK 10也有一些主要特性。這些特性可以分為兩個(gè)主要類別:(1)目標(biāo)發(fā)布,(2)建議發(fā)布。前者表示某些特性已計(jì)劃在JDK 10中發(fā)布,后一種類型表示這些特性還需要增加支持和成熟度。一旦條件允許,它就可以升級(jí)為一個(gè)目標(biāo)發(fā)布狀態(tài)。
目標(biāo)發(fā)布
目前有兩個(gè)主要功能針對(duì)JDK 10:
- 局部變量類型推斷,這將刪除大部分對(duì)象實(shí)例化所需的冗長(zhǎng)的包含手動(dòng)類型信息
- 整合源樹(shù)source tree的JDK庫(kù),即不同的JDK庫(kù)將被合并成一個(gè)單一的存儲(chǔ)庫(kù)。
1. 局部變量類型推斷
強(qiáng)類型編程語(yǔ)言有很多優(yōu)點(diǎn),包括在編譯時(shí)發(fā)現(xiàn)類型錯(cuò)誤,但是它們也引入了大量的樣板代碼,特別是在定義局部變量時(shí)。例如,當(dāng)我們希望實(shí)例化一個(gè)對(duì)象時(shí),我們被迫在賦值的左側(cè)提供顯式類型,并在賦值的右邊提供實(shí)現(xiàn)類型,如下面的片段所示:
- MyObject value = new MyObject();
但是,當(dāng)這個(gè)過(guò)程重復(fù)出現(xiàn)大量任務(wù)時(shí),對(duì)象實(shí)例化可能變得令人沮喪和乏味。許多最流行的強(qiáng)類型的編程語(yǔ)言,比如C++, C#以及Go,在定義過(guò)程中,提供一種局部變量類型推斷的功能(例如C++提供了auto 關(guān)鍵字,C#提供var關(guān)鍵字)。但是,Java仍缺乏這樣的功能,它要求開(kāi)發(fā)人員顯式聲明變量的預(yù)期清單類型。
為了解決這個(gè)問(wèn)題,Java開(kāi)發(fā)工具包(JDK)改進(jìn)建議(JEP)286提出了一個(gè)上下文敏感的關(guān)鍵字var,允許局部變量被以下方式初始化:
- var value = new MyObject();
- var list = new ArrayList();
由于var關(guān)鍵字是上下文敏感的,它的使用有下面的規(guī)則定義:
- 代碼使用var作為一個(gè)變量、方法或包名稱時(shí)將不受影響;而使用var作為類或接口名稱的代碼將受到影響。
同樣,類型推斷將受到以下方式的約束:
- 推斷類型將被限制在局部變量的初始化,增強(qiáng)的for循環(huán)索引,以及傳統(tǒng)的for循環(huán)中聲明;它(將)不用于方法形式、構(gòu)造函數(shù)形式、方法返回類型、字段、捕獲形式,或任何其他類型的變量聲明。
考慮到所有的限制和細(xì)微差別,這個(gè)特性將有助于在開(kāi)發(fā)人員創(chuàng)建的應(yīng)用程序Java代碼中減輕大量的單調(diào)無(wú)聊的動(dòng)作,并簡(jiǎn)化JDK代碼庫(kù)。更多信息可以在官方的JEP 286規(guī)范中找到。
2. 整合的JDK庫(kù)
目前,有8個(gè)不同的Mercurial存儲(chǔ)庫(kù)用于存儲(chǔ)包含JDK的大量源代碼:
- root
- corba
- hotspot
- jaxp
- jaxws
- JDK
- langtools
- nashorn
雖然過(guò)多的存儲(chǔ)庫(kù)提供了對(duì)組成JDK的各種組件并清晰分離,但管理多個(gè)存儲(chǔ)庫(kù)存在一些主要的缺點(diǎn)。
其中最重要的一點(diǎn)是,在JDK的兩個(gè)不同部分,單個(gè)錯(cuò)誤修復(fù)程序不能被原子跟蹤。例如,如果一個(gè)bug修復(fù)需要對(duì)獨(dú)立存儲(chǔ)庫(kù)中包含的系統(tǒng)的兩個(gè)部分進(jìn)行更改,那么必須提交兩個(gè)提交:每個(gè)存儲(chǔ)庫(kù)中一個(gè)。這種不連續(xù)性很容易地降低項(xiàng)目和源代碼管理工具的可跟蹤性和復(fù)雜性。
為了解決這個(gè)問(wèn)題,JEP 296建議將所有現(xiàn)有存儲(chǔ)庫(kù)合并到一個(gè)Mercurial存儲(chǔ)庫(kù)中。這種合并的一個(gè)次生效應(yīng)是,這個(gè)單一的Mercurial存儲(chǔ)庫(kù)比現(xiàn)有的8個(gè)存儲(chǔ)庫(kù)要更容易的被鏡像(作為一個(gè)Git存儲(chǔ)庫(kù))。
雖然在這個(gè)整合過(guò)程中,外部開(kāi)發(fā)人員有一些阻力,但是JDK開(kāi)發(fā)團(tuán)隊(duì)似乎已經(jīng)致力于使這一更改成為JDK 10的一部分。有關(guān)更多信息,請(qǐng)參見(jiàn)JEP 296,并提議整合由Michael Redlich發(fā)布的JDK 10 OpenJDK Mercurial存儲(chǔ)庫(kù)聲明。
建議發(fā)布
除了兩個(gè)目標(biāo)特性之外,JDK 10目前還有三個(gè)建議,其中兩個(gè)主要是對(duì)JDK的垃圾收集器部分進(jìn)行升級(jí),另一個(gè)側(cè)重于對(duì)JDK的本地線程功能進(jìn)行升級(jí)。
1 .清理垃圾收集接口
在當(dāng)前的JDK結(jié)構(gòu)中,組成垃圾收集器(GC)實(shí)現(xiàn)的組件分散在代碼庫(kù)的各個(gè)部分。盡管這些慣例對(duì)于使用GC計(jì)劃的JDK開(kāi)發(fā)者比較熟悉,但對(duì)新的開(kāi)發(fā)人員來(lái)說(shuō),對(duì)于特定GC的源代碼,或者創(chuàng)建一個(gè)新的GC常常會(huì)感到困惑。更重要的是,隨著Java modules的出現(xiàn),我們希望在構(gòu)建過(guò)程中排除不需要的GC,但是GC接口的當(dāng)前橫切結(jié)構(gòu)排除了這種增強(qiáng)。
JEP 304被設(shè)計(jì)為解決此問(wèn)題的方案,并建議整合并清理GC接口,以便更容易地實(shí)現(xiàn)新的GC,并更好地維護(hù)現(xiàn)有的GC。本建議完成后,GC執(zhí)行將負(fù)責(zé)提供以下內(nèi)容:
- heap,CollectedHeap的子類
- barrier set,BarrierSet的子類,它實(shí)現(xiàn)了運(yùn)行時(shí)的各種障礙
- 一個(gè)CollectorPolicy的實(shí)現(xiàn)
- GCInterpreterSupport的實(shí)現(xiàn),它實(shí)現(xiàn)了解釋器的GC的各種障礙(使用匯編指令)
- GCC1Support的實(shí)現(xiàn),它為C1編譯器實(shí)現(xiàn)了GC的各種障礙
- GCC2Support的實(shí)現(xiàn),它為C2編譯器實(shí)現(xiàn)了GC的各種障礙
- 最終GC特定參數(shù)的初始化
- 設(shè)置MemoryService、相關(guān)的內(nèi)存池、內(nèi)存管理器等。
有關(guān)這些更改的更多信息,請(qǐng)參見(jiàn)JEP 304規(guī)范;有關(guān)Java GC的更多信息,請(qǐng)參閱Oracle提供的垃圾收集器基礎(chǔ)指南。
2. G1垃圾收集器并行化
隨著JDK 9的發(fā)布,Garbage-First(G1)GC取代了Parallel Collector作為默認(rèn)GC。為了減少JDK 9之外的JDK版本中垃圾收集的影響,G1收集器將被并行化(以匹配并行收集器的特征)。雖然目前還沒(méi)有關(guān)于這個(gè)并行化的實(shí)現(xiàn)細(xì)節(jié)的信息,但是可以在JEP 307規(guī)范中找到關(guān)于此更改的更多細(xì)節(jié)。
有關(guān)GC實(shí)現(xiàn)的更多信息,請(qǐng)參閱Oracle的G1指南和并行收集器指南。
3. 項(xiàng)目線程局部握手
當(dāng)前,停止Java線程是一個(gè)“全部或沒(méi)有”的過(guò)程,需要一個(gè)Java虛擬機(jī)(JVM)的安全點(diǎn),以使一個(gè)線程停止。為了讓單獨(dú)的線程停止,JEP 312提議將回調(diào)包含到線程中。這一更改受到了限制,因?yàn)樗@著地提高了現(xiàn)有JVM功能的性能開(kāi)銷,并且改變了到達(dá)JVM全局安全點(diǎn)的現(xiàn)有時(shí)間語(yǔ)義。有關(guān)這個(gè)建議的更多信息,請(qǐng)參閱JEP 312的Thread-Local Handshake OpenJDK討論。
結(jié)論
盡管JDK 9對(duì)于許多Java開(kāi)發(fā)人員非常新鮮,但它的發(fā)展并沒(méi)有停止。特別是,JDK 10承諾為局部變量實(shí)例化引入類型推斷機(jī)制,并將現(xiàn)有的JDK存儲(chǔ)庫(kù)合并到一個(gè)Mercurial存儲(chǔ)庫(kù)中。
此外,在更成熟和更支持的情況下,JDK 10還可能包括一些重要的升級(jí)到GC接口和默認(rèn)的GC實(shí)現(xiàn),以及升級(jí)到JVM中單個(gè)線程的可尋址能力。雖然JDK 10的發(fā)布在未來(lái)仍然相對(duì)較遠(yuǎn),而且包含的特性很可能會(huì)成為Java時(shí)間軸上的一個(gè)重要里程碑。