一文了解 Java 各發行版本及新特性


一文了解 Java 各發行版本及新特性

本文幫助您獲取Java最新版與安裝實用信息,了解Java各發行版(AdoptOpenJdk、OpenJDK、OracleJDK 等)之間差異,對Java 8-13中的新特性進行概覽。

 

實用信息

 

首先,看一下為項目選擇正確的Java版本時可能遇到的一些常見問題。

 

其他的都知道了,我只要一個下載鏈接。應該去哪兒?

 

打開網站AdoptOpenJDK選擇最新的Java版本,然后下載安裝。然后回來,興許還可以學習一兩個有用的Java版本知識。

 

應該使用哪個Java版本?

 

截至2019年9月,Java 13是最新的Java版本,而且每6個月會發布一個新版本。Java 14計划於2020年3月發布,Java 15計划於2020年9月發布,以此類推。過去,Java的發行周期更長,甚至3到5年才發布一次!

 

 

隨着眾多新版本的發布,現實中會出現下面這樣的場景:

 

  • 公司的老項目被困在Java 8上。因此,您可能也會被迫使用Java 8。

  • 有些舊項目甚至困在Java 1.5(2004年發布)或1.6(2006年發布)上。真心為這些朋友感到難過!

  • 如果決定使用最新的 IDE、框架和構建工具並啟動一個全新的項目,可以毫不猶豫使用地Java 11(LTS)或者最新的Java 13。

  • Android開發是一個特殊領域,版本基本上停留在Java 7,提供一部分Java 8支持。當然,您也可以切換到Kotlin編程語言。

 

為什么有些公司仍然堅持使用Java 8?

 

原因多種多樣,下面是其中幾個:

 

  • 構建工具(比如 Maven、Gradle等)以及某些開發庫在 Java 8或者更高版本上運行有bug,需要更新。直到今天,一些工具在Java 9+下構建項目時會打印 "reflective access"-warnings。即使生成的結果沒問題,也會讓人“感覺沒有就緒”。

  • 一直到Java 8,使用Oracle JDK都不用關心許可證。但是,Oracle 在2019年改變了許可證方案。互聯網上一石激起千層浪。其中很多文章聲稱“Java不再免費了”,出現了各式各樣的困惑。其實這不是問題,接下來的Java 發行版部分會仔細介紹。

  • 有些公司規定只用LTS版本,並且通過操作系統供應商提供發布,這個過程需要一些時間。

 

小結一下:實際工作中會遇到一系列問題,諸如工具升級、開發庫升級、框架升級,還有公司規定等等。

 

為什么Java 8也叫1.8?

 

Java 9以前采用了另一套版本命名規則。Java 8可以叫1.8,Java 5也可以叫1.5等。執行“java -version”命令,輸出版本信息如下:

 

c:\Program Files\Java\jdk1.8.0_191\bin>java -version
java version "1.8.0_191" (1)
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

 

簡而言之就是Java 8。隨着Java 9切換為按時間發布新版本,版本命名方案也發生了變化,不再用1.x作為前綴。現在的版本號像下面這樣:

 

c:\Program Files\Java\jdk11\bin>java -version
openjdk version "11" 2018-09-25 (1)
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

 

各個Java版本之間有什么區別?要不要挑選某個版本學習呢?

 

編程語言不同發布版本之間差異很大,像Python 2和Python 3。同樣的邏輯是不是Java也適用?

 

Java向后兼容,不會出現這種情況。這意味着,除了少數例外,Java 5或Java 8的程序可以在Java 8-13虛擬機上運行。

 

當然,反過來則不成立。如果程序用到了Java 13一些特性,而Java 8 JVM根本不具備這些功能,顯然無法工作。

 

這意味着兩點:

 

  • 不會只是“學習”某個特定版本的Java,比如Java 12。

  • 相反,之前掌握的Java 8功能都為您打下了良好的基礎。這是非常好的基礎。

  • 接下來,可以從本文這樣的指南中學習使用Java 9-13新增功能。

 

Java各個版本都有哪些新功能?

 

一起了解Java 8-13新特性。

 

按照經驗:Java版本越早發行周期越長(比如3到5年,一直到Java 8),這意味着每個發行版包含更多新功能。

 

6個月的發布周期意味着每個版本包含的新功能要少得多,因此可以快速掌握Java 9-13的新功能。

 

JRE和JDK有什么區別?

 

目前為止,一直討論的是“Java”。Java到底是什么?

 

首先需要區分JRE和JDK。

 

過去,如果運行Java程序,只下載JRE就可以了。JRE包含Java虛擬機(JVM)和“java”命令行工具。

 

如果開發Java程序,需要下載一個JDK。JDK除了包含JRE中的所有內容,還提供了javac編譯器及一些工具,比如javadoc(Java文檔生成器)和jdb(Java Debugger)等。

 

為什么要用“過去”這種說法?

 

直到Java 8,盡管JDK有一個獨立的JRE文件夾,Oracle網站還是把JRE和JDK作為單獨文件提供下載。到Java 9這種區別沒有了,只有JDK下載。與此同時,JDK的目錄結構也變了,不再出現獨立的JRE文件夾。

 

雖然某些發行版(參見Java發行版章節)仍然可以單獨下載JRE,只提供JDK似乎已經成為一種趨勢。從現在開始,Java與JDK可以替換使用。

 

如何安裝Java?

 

先不考慮Java-Docker鏡像、.msi安裝包或者平台特定的軟件包。歸根到底Java只是一個.zip文件,僅此而已。

 

在計算機上安裝Java只需要解壓縮jdk-{5-13}.zip文件,甚至都不需要管理員權限。

解壓縮后的Java文件如下:

 

Directory C:\dev\jdk-11

12.11.2019 19:24 <DIR> .
12.11.2019 19:24 <DIR> ..
12.11.2019 19:23 <DIR> bin
12.11.2019 19:23 <DIR> conf
12.11.2019 19:24 <DIR> include
12.11.2019 19:24 <DIR> jmods
22.08.2018 19:18 <DIR> legal
12.11.2019 19:24 <DIR> lib
12.11.2019 19:23 1.238 release

 

區別在於/bin目錄,Windows下看起來像這樣:

 

Directory C:\dev\jdk-11\bin
...
12.11.2019 19:23 272.736 java.exe
...
12.11.2019 19:23 20.832 javac.exe
...

 

因此,唯一需要做的就是解壓縮文件,把/bin目錄加到PATH變量,以便從任何地方都可以調用“java”命令。

 

(Oracle或AdoptOpenJDK提供的圖形化安裝程會替您執行解壓縮和修改PATH變量操作)

 

驗證是否正確安裝好Java,只要運行“java -version”。如果輸出看起來像下面這樣表示安裝成功。

 

openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

 

還剩下一個問題:從哪里獲得Java .zip文件?我們接着討論Java發行版。

 

Java發行版

 

有各種網站提供Java下載,但是不清楚“提供的內容以及采用怎樣的許可”。本節會對此進行討論。

 

OpenJDK項目

 

就源代碼而言,只有一套Java源代碼,存在OpenJDK項目中。

 

但只是源代碼,不是發布版本(.zip文件中針對特定操作系統編譯好的Java命令)。理論上,您可以從源代碼構建一個版本然后發布,把它叫做MarcoJDK好了。但是這個發行版缺少認證,不能對外號稱與Java SE兼容。

 

這就是為什么一些供應商會自己構建、進行認證(參見TCK)然后發布。

 

盡管供應商不能從String類中刪除方法,但是可以添加商標或者他們認為有用的其他實用程序(比如CLI)。除此之外,所有Java發行版的源代碼都是一樣的。

 

OpenJDK Build(Oracle提供)與OracleJDK Build

 

Oracle是Java供應商之一,這樣產生了兩種不同的Java發行版,開始可能會覺得非常混亂。

 

  1. OpenJDK Build(Oracle提供)。這些Build是免費且沒有商標的。但是Oracle不會對之前的老版本發布更新,舉個例子,在Java 14推出后不會立即發布Java 13更新。

  2. 從2019年更改許可證開始,OracleJDK變成了帶商標的商業版。開發期間可以免費使用,但如果在生產環境中使用就需要向Oracle付費。付費后能夠享受長期支持,包括新版本升級,如果JVM出現問題可以享受電話支持。

 

Java 8之前,OpenJDK和OracleJDK的源代碼實際上不一樣,可以說OracleJDK“更好”。時至今日,兩個版本幾乎相同,只有細小差別。

 

歸結起來,付費的Java商業版為您提供的就是電話支持。

 

AdoptOpenJDK

 

2017年,一群Java用戶組(JUG)成員、開發者和供應商(包括亞馬遜、微軟、Pivotal、Redhat等)建立了一個社區稱作AdoptOpenJDK。

 

他們提供免費、穩固的OpenJDK build,可用性與更新周期更長。甚至還有兩個不同的Java虛擬機可供選擇:HotSpot和OpenJ9。

 

如果安裝Java,強烈推薦

 

Azul Zulu、Amazon Corretto、SAPMachine。

 

在OpenJDK Wikipedia網站上可以找OpenJDK build完整的列表。其中包括Azul Zulu、Amazon Corretto以及SapMachine其他版本。為了便於比較,這個列表按照不同的支持選項與維護策略進行了分類。

 

要了解每個發行版本的優勢,請務必查看各個網站。

 

建議

 

2019年開始,除非有非常特殊的要求,否則請從https://adoptopenjdk.net獲取jdk.zip (.tar.gz/.msi/.pkg)或者從操作系統供應商提供的軟件中選擇。

 

Java 8-13新特性

 

正如本文開頭提到的:基本上所有Java 8功能都可以在Java 13中使用。兩個版本中間所有其它版本也是如此。

 

也就是說,Java 8所有功能都可以作為Java基礎知識,Java 9-13中增加的可以看作額外的新增功能。

 

以下是各版本的功能概括:

 

-Java 8-

 

Java 8版本功能非常龐大,可以在Oracle網站上找到所有功能列表。不過,這里要提到兩個主要功能:

 

語言特性:Lambda。

 

Java 8之前,如果要實例化比如一個新的Runnable,都必須寫一個匿名內部類,像下面這樣:

 

Runnable runnable = new Runnable(){
@Override
public void run(){
System.out.println("Hello world !");
}
};

 

使用Lambd等價代碼如下:

 

Runnable runnable = () -> System.out.println("Hello world two!");

 

此外,Java 8還提供了方法引用、重復注解,接口默認方法及其他功能。

 

Collection與Stream

 

Java 8還為Collection加入了函數式操作,也稱為Stream API。簡單示例:

 

List<String> list = Arrays.asList("franz", "ferdinand", "fiel", "vom", "pferd");

 

Java 8之前的版本,必須寫for循環才能對列表進行處理。

 

使用Streams API可以執行下面的操作:

 

list.stream()
.filter(name -> name.startsWith("f"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);

 

練習Java 8

 

限於篇幅,這里只能概括介紹Java 8的Stream、Lambda或Optional方法,

 

想要更詳細、更全面的了解和練習,可以看一下Java 8核心功能課程。

 

-Java 9-

 

Java 9也是一個大版本,其中增加了一些功能:

 

Collections

 

Collections增加了幾個新的helper方法,可以很方便地構造List、Set和Map。

 

List<String> list = List.of("one", "two", "three");
Set<String> set = Set.of("one", "two", "three");
Map<String, String> map = Map.of("foo", "one", "bar", "two");

 

Stream

 

Stream加入了takeWhile、dropWhile、iterate方法提供了額外功能。

 

Stream<String> stream = Stream.iterate("", s -> s + "s")
.takeWhile(s -> s.length() < 10);

 

Optionals

 

Optionals增加了迫切需要的ifPresentOrElse方法。

 

user.ifPresentOrElse(this::displayAccount, this::displayLogin);

 

接口

 

接口增加了私有方法:

 

public interface MyInterface {

private static void myPrivateMethod(){
System.out.println("Yay, I am private!");
}
}

 

其他語言特性

 

Java 9還有其他一些改進,例如改進了try-with-resources、菱形運算符擴展等。

JShell

 

最后,Java 9提供了一個shell,可以執行簡單的命令並立即返回結果。

 

% jshell
| Welcome to JShell -- Version 9
| For an introduction type: /help intro

jshell> int x = 10
x ==> 10

 

HTTPClient

 

Java 9提供了HttpClient新的初始預覽版。在此之前,Java內置的Http支持還是相當底層,不得不依靠Apache HttpClient或者OkHttp這樣的三方庫。

 

Java 9開始,Java有了更現代的client。雖然還是預覽模式,但意味着在新的Java版本中會繼續改進。

 

Jigsaw項目:Java模塊化與多版本jar文件

 

Java 9提供了Jigsaw模塊系統,有點像過去的OSGI規范。了解更多Jigsaw項目信息可點擊鏈接查看。

 

多版本.jar文件讓一個.jar文件包含適用於不同JVM版本的class成為可能。例如,程序在Java 8與Java 10上運行時,可以提供不同的class。

 

練習Java 9

 

同樣,這里只是快速瀏覽Java 9功能,如果需要更詳盡的解釋和練習,請查看Java 9核心功能課程。

 

-Java 10-

 

Java 10也進行了一些改變,像垃圾回收等。作為開發人員,唯一可能真正看到的變化就是引入了“var”關鍵字,也稱為局部變量類型推斷。

 

局部變量類型推斷:var關鍵字

 

// Java 10之前的版本

String myName = "Marco";

// 使用Java 10

var myName = "Marco"

 

感覺很像Javascript對吧?不過,這里仍然是強類型,而且僅適用於方法內部變量(感謝,dpash再次指出這一點)。

 

-Java 11-

 

從開發人員的角度來看,Java 11的變化也很小。

 

字符串與文件

 

字符串與文件加入了一些新方法(此處未列出所有方法):

 

"Marco".isBlank();
"Mar\nco".lines();
"Marco ".strip();

Path path = Files.writeString(Files.createTempFile("helloworld", ".txt"), "Hi, my name is!");
String s = Files.readString(path);

 

運行源文件

 

Java 10開始,可以不用編譯直接運行Java源文件。這是邁向腳本化的一步。

 

ubuntu@DESKTOP-168M0IF:~$ java MyScript.java

 

Local-Variable Type Inference (var) for lambda parameters

 

header信息說明了一切:

 

(var firstName, var lastName) -> firstName + lastName

 

HttpClient

 

HttpClient完成了最終非預覽版本。

 

其他改變

 

Java 10加入了Flight Recorder、無操作垃圾收集器,棄用了Nashorn Javascript引擎等。

 

-Java 12-

 

Java 12加入了一些新特性和清理功能。這里唯一值得一提的是Unicode 11支持和新的switch表達式預覽版,下一節會看到它。

 

-Java 13-

 

在這里可以找到完整功能列表。Java 13支持Unicode 12.1,加入了兩個新的預覽功能(未來可能會更改):

 

Switch表達式(預覽功能)

 

switch表達式現在可以返回一個值。而且可以對表達式使用lambda風格的語法,不會出現fall-through/break問題:

 

過去的switch語句看起來像下面這樣:

 

switch(status) {
case SUBSCRIBER:
//代碼塊
break;
case FREE_TRIAL:
//代碼塊
break;
default:
//代碼塊
}

 

Java 13中的switch語句:

 

boolean result = switch (status) {
case SUBSCRIBER -> true;
case FREE_TRIAL -> false;
default -> throw new IllegalArgumentException("something is murky!");
};

 

多行字符串(預覽功能)

 

終於可以在Java中執行這樣的操作:

 

String htmlBeforeJava13 = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";

String htmlWithJava13 = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";

 

Java 14及更新版本

 

新版本一單發布,會在這里進行介紹。到時記得來看哦。

 

結語

 

到此為止,您應該對以下幾件事有了一個很好的了解:

 

  • 如何安裝Java、選擇哪個版本以及從哪里下載(提示:AdoptOpenJDK)。

  • Java發行版是什么、有哪些選擇、各自有什么區別。

  • Java各個版本之間有什么區別。

 

歡迎反饋、更正和建議!請在下方評論。

 

感謝閱讀。

 

致謝

 

關於Java發行版及區別,Stephen Colebourne寫了一篇很棒的文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM