JDK 10 的新特性和加強功能

本文是對底部參考資料的整理獲得的,因爲本人技術水平和英語水平都不是很高,有些詞若有翻譯錯誤或句子的理解錯誤還請指出。

JEP 286 局部變量推斷: var

傳統的 Java 代碼中,聲明一個變量是很是繁瑣的:html

List<String> list = new ArrayList<String>();

如今則引入了 var,既保持 Java 對靜態類型安全的承諾,又能讓開發者省略沒必要要的局部變量類型的聲明。java

好比像這樣:程序員

var list = new ArrayList<String>();

var 只能用在如下狀況:算法

  • 聲明的同時賦值,好比上面那個例子
  • 加強的 for 循環中的索引 (這將在後面提到)
  • 傳統 for 循環中聲明的本地變量

它不能被用於方法簽名、構造器聲明、方法返回類型、字段、異常捕獲或任何其餘類型的變量聲明。數組

類型推斷在 Java 8 中已經獲得了顯著的擴展,包括了對嵌套和連接的泛型方法的推導以及 lambda 表達式的推導,好比下面這樣:安全

int maxWeight = blocks.stream()
                    .filter(b -> b.getColor() == BLUE)
                    .mapToInt(Block::getWeight)
                    .max();

沒有必要去在乎 blocks.stream*() 返回的是 Stream<Block>,也不用在乎 filterlambda 表達式的參數類型沒有被顯式聲明,由於它們都能經過類型推導獲得。oracle

對於局部類型變量,類型推導是很是有用的,由於一般狀況下均可以寫成下面這種代碼:框架

var path = Paths.get(fileName);
var bytes = Files.readAllBytes(path);

可是要注意的是,var 並非一個關鍵字,而是一個保留的類型名稱,這意味着你能夠將一個變量、方法、包名寫成 var 。不過通常狀況下不會有人這麼寫的,由於這自己就違反了廣泛的命名規範。工具

var 不能用來聲明沒有賦值的變量、不能用於聲明多個變量的狀況、不能聲明具備額外緯度的數組或引用了正在初始化的其餘變量的變量。oop

JEP 322 基於時間的版本號管理

JEP 223 引入的版本號方案相比以前的方法都要好不少,可是對於如今 Java 所走的 六個月節奏 並不適合。

JEP 223 的問題在於,版本號中編碼了它和它對以前版本的兼容性信息。可是在 六個月節奏 的狀況下,這些信息都是未知的,在發佈前任何事情均可能發生,由此 JEP 223 規範下的版本號也會是未知的。

JEP 223 的語義中,每一個基於 JDK 構建或使用組件的開發者(包括 JDK 的發佈者)都必須提早敲定版本號,而後切換過去。而庫、框架和工具的開發者則必須在代碼中修改檢查版本號的相關代碼,這形成了混亂。

更多關於 JEP 322 的詳細狀況請訪問這裏

core-libs/java.util Optional.orElseThrow() 方法

這次更新中爲 Optional 類添加了一個新的方法,這個方法與 orElseThrow(exSupplier) 是不一樣的,它沒有參數。

Optional.get() 是一個容易誤導程序員的方法,它實際上有可能拋出 NoSuchElementException 運行時異常,所以須要一個語義明確的方法來幫助程序員清楚的認識到本身在作什麼。

在以前的規劃中,Optional.getWhenPresent() 是一個備選方法,雖然這個名字強調了值必定會存在,可是其中的 when 彷佛會讓人以爲這是個阻塞方法。所以最後委員會選擇了 Optional.orElseThrow(),可是 Optional.get() 並無被單純得棄用。

Unicode 標籤擴展

加強了 java.util.Locale 和相關 API 以實現關於 BCP 47 語言標籤Unicode 擴展。

詳情請訪問這裏

core-libs/java.util 建立不可變集合的一系列 API

新的 API 中包括了一些用於建立不可見集合的方法:

List.copyOfSet.copyOfMap.copyOf() 能夠用來從已有的集合中建立一個新的集合;

toUnmodifiableListtoUnmodifiableSettoUnmodifiableMap 則存在於 Stream.Collectors 類中,經過它們能夠將流的元素收集到一個不可變集合當中。

copyOf 系列的方法簽名基本是下面這樣:

static <T> List <T> copyOf (Collection <? extends T> coll)

SetMap 也會有相似的方法。

值得注意的是,這個方法會檢測 coll 是否是一個 不可變 的集合,若是是,則會直接返回該引用,至關於一個淺拷貝。

另外對於不可變集合而言,下面這種狀況是被容許的:

List <String> list = List.of(...);
List <CharSequence> newList = List.copyOf(list);

這對於可變集合而言是不容許的,由於這可能會致使堆污染。

core-svc/java.lang.management 用於關閉 JRE Last Usage Tracking 的系統屬性

引入了新的 jdk.disableLastUsageTracking 屬性以禁用 JVMJRE 上次使用狀況追蹤 功能。

若是使用了此屬性,那麼 com.oracle.usagetracker.track.last.usage 的設置將被忽略。

core-svc/java.lang.management 開箱即用的 JMX 代理使用的散列密碼

在之前,JMX 存儲的是明文密碼,當時 (2014 年) 你們已經開始手動生成散列密碼來替換明文密碼,由於這能夠避免一些攻擊,同時鹽 (salt) 的存在可讓散列密碼的強度更上一層。可是對於管理員而言,即便是使用諸如 Python 之類的腳本語言來生成散列密碼,這仍然是極容易出錯的。所以最好的辦法是用戶只須要提供明文密碼,讓 JMX 來處理散列之類的事情。

JMX 如今會使用密碼的 SHA3-512 散列結果來覆蓋存儲在 jmxremote.password 中的明文密碼。

其格式以下:

role_name W hashedPassword

其中:

  • role_name 是任何不含空格或製表符的字符串
  • W 是一個空格或製表符

散列密碼的格式以下:

hashedPassword = base64_encoded_64_byte_salt W base64_encoded_hash W hash_algorithm

其中:

  • base64_encoded_64_byte_salt 是 64字節的隨機值
  • base64_encoded_hashHash_algorithm(password + salt) 的結果
  • W 是一個空格或製表符
  • hash_algorithm列表 中指定的算法名稱。這是個可選項,默認值爲 SHA3-512

若是密碼是明文的,且知足如下條件,那麼將被散列值覆蓋

  1. management.properties 文件中 com.sun.management.jmxremote.password.toHashes 屬性被設爲 true
  2. 密碼文件是可寫的
  3. 安全管理器處於打開狀態的狀況下系統安全策略容許對密碼文件進行寫入

若是想更改角色的密碼,能夠將舊的散列密碼替換爲新的明文密碼或新的散列密碼。若是新的密碼是明文的,那麼在新的登陸發生時系統會使用其散列值替換明文密碼。

文件中的角色應該至少有一條記錄,不然該角色將無權訪問;若是同一個用戶下有多條記錄,那麼會使用最後一條記錄。

用戶能夠自行根據上述的格式來生成的散列值,以替換舊的密碼。

文件被擁有者之外的用戶訪問時將致使錯誤並退出程序。

爲了防止在生產環境中對密碼文件進行了無心的編輯,建議只部署可讀的散列密碼文件。明文密碼的散列密碼列表能夠用 JMX 代理預先生成。

JMX 運行期間,建議不要編輯密碼文件。程序會對文件的完整性作一個保護,所以修改既可能丟失。

hotspot/gc JEP 307 G1 的 徹底並行 GC

G1 垃圾收集器就是爲了不 徹底 GC (full collections) , 可是當並行收集沒法快速回收內存時,會產生一次 徹底回退 GC (fall back full GC) 。

以前 G1徹底GC 使用的是單線程標記掃描壓縮算法(mark-sweep-compact),如今經過 JEP 307徹底GC 得以並行化,同時如今會使用與 年輕代混合收集 相同的並行工做線程數量。

security-libs/java.security JEP 319 根證書

OpenJDK 中的 cacerts 密鑰庫在至關長一段時間內是空的,這將致使未指定 javax.net.ssl.trustStore 屬性的狀況下 TLS 鏈接 的建立會被阻止。如今OracleJava SE 根證書 被填充至 OpenJDKcacerts 中。

security-libs/javax.net.ssl TLS 會話散列主密鑰擴展 的支持

在是一個對 RFC 7627 的支持。

若是出現兼容問題,能夠將 jdk.tls.useExtendedMasterSecret 設置爲 false 來禁用此擴展的協商。

若是 jdk.tls.allowLegacyResumption 值爲 false,當會話散列和主密鑰擴展未協商的狀況下,程序能夠拒絕簡短握手。

若是 jdk.tls.allowLegacyMasterSecret 值爲 false,應用將拒毫不支持此擴展的鏈接。

tools/javac 加強 for 循環的字節碼生成

以前的 for 循環在遍歷一個大的列表/數組時,它會隱式得持有一個臨時引用,並且這個臨時引用不會被釋放以致於可能產生 OutOfMemoryError 異常,詳細的狀況能夠查看這裏

對於下面的 Java 代碼:

List<String> data = new ArrayList<>();
for (String b : data);

將會被編譯爲:

{
    /*synthetic*/
    Iterator i$ = data.iterator();
    for (; i$.hasNext(); ) {
        String b = (String) i$.next();
    }
    b = null;
    i$ = null;
}

這意味着 GC 能夠發現再也不被使用的 i$ 所佔用的內存並回收它,這對於數組也是適用的。

tools/javadoc(tool) javadoc 支持多個樣式表

新的 javadoc 命令行選項 --add-stylesheet ,它支持在生產的文檔中使用多個樣式表。

而現有的選項 -stylesheetfile 有了一個別名 stylesheetfile --main-stylesheet,用以區分主樣式表和其餘樣式表,更多信息能夠查看 javadoc 文檔

tools/javadoc(tool) 覆寫沒有改變規範的方法

默認狀況下,若是有方法覆寫了超類中的方法,那麼 javadoc 會爲它生成文檔。

可是若是一個方法只是被覆寫可是沒有改變語義行爲時,javadoc 只會在原方法摘要中用 @inheritdoc 標記它。

如今新的選項 --overridden-methods=value 能夠將許多 不改變規範的覆寫方法 與其餘繼承而來的方法分組,而不是在類的聲明中與其餘方法一塊兒被記錄在文檔中。

tools/javadoc(tool) API 描述中摘要的註釋標記

{@summary ...} 是一個新的行內標記。默認狀況下,會經過簡單算法或 java.text.BreakIterator 對描述中的第一句話進行判斷以肯定 API 描述內容的摘要,可是這種方法可能會對第一句話結尾有錯誤的判斷,所以新的標籤能夠顯式得指定 API 的描述摘要。

參考資料

相關文章
相關標籤/搜索