聊聊 Java8 以后各个版本的新特性
【這是 ZY 第 11 篇原創技術文章】
某天在網上閑逛,突然看到有篇介紹 Java 11 新特性的文章,頓時心里一驚,畢竟我對于 Java 的版本認識還停留在 Java 8 上,而日常使用的語法和 API 還停留在 Java 7 上。于是抽時間看了看 Java 8 以后各個版本的特性,做了一個總結。
文章概覽
JDK
JDK 全稱 Java Development Kit,是 Java 開發環境。我們通常所說的 JDK 指的是 Java SE (Standard Edition) Development Kit。除此之外還有 Java EE(Enterprise Edition)和 Java ME(Micro Edition platforms)。
Java 的發布周期
| JDK Beta | 1995 | WebRunner |
| JDK 1.0 | 1996.1 | Oak |
| JDK 1.1 | 1997.2 | |
| J2SE 1.2 | 1998.12 | Playground |
| J2SE 1.3 | 2000.5 | Kestrel |
| J2SE 1.4 | 2002.2 | Merlin |
| J2SE 5.0 | 2004.9 | Tiger |
| Java SE 6 | 2006.12 | Mustang |
| Java SE 7 | 2011.7 | Dolphin |
| Java SE 8 (LTS) | 2014.3 | |
| Java SE 9 | 2017.9 | |
| Java SE 10 (18.3) | 2018.3 | |
| Java SE 11 (18.9 LTS) | 2018.9 | |
| Java SE 12 (19.3) | 2019.3 | |
| Java SE 13 (19.9) | 2019.9 |
下面我們看一些 Java 發展過程中重要的節點。
1995 年 alpha 和 beta Java 公開版本發布,取名為 WebRunner。
1996.1.23 Java 第一個版本發布,取名叫 Oak。但是第一個穩定版本是 JDK 1.0.2,被稱做 Java 1。
1998.12.8 發布了 J2SE 1.2。這個版本到 J2SE 5.0 更名為 Java 2。其中的 SE 指的是 Standard Edition,為了區別于 J2EE(Enterprise Edition)和 J2ME(Micro Edition)。
2000.5 發布了 J2SE 1.3,其中包含了 HotSpot JVM。而 HotSpot JVM 首次發布是在 1999.4,名為 J2SE 1.2 JVM。
2004.9.30 發布了 J2SE 5.0。為什么這個版本命名和前面幾個版本不一樣呢?這個版本原本計劃以 1.5 命名的,沿用以前的命名方式。但是為了更好的反映這個版本的成熟度,所以改名為 5.0。
這個版本以后,有了一個新的版本控制系統,5.0 用來表示產品版本,用來表示穩定的 J2SE 版本,而 1.5.0 用來表示開發者版本,也就是 Java 5.0 = JDK 1.5.0。
2006.12.11,J2SE 改名為 Java SE,版本號去掉了 .0。此后對應版本就是 Java 6 = JDK 1.6,Java 7 = JDK 1.7。
2011.7.7. 發布 Java SE 7,是一個重大版本更新。更新了眾多特性。
2018.3 發布 Java SE 10。在此之前,Java 基本上是兩年一個版本,除了 Java SE 7 經過了五年,Java SE 8 經過了三年。在此之后,就是每六個月發布一次新版本。但是不是每個版本都是 LTS(Long-Term-Support)。按照 Oracle 的計劃,每三年會有一個 LTS 版本。最近的 LTS 版本就是 Java SE 11 了。
OpenJDK VS Oracle JDK
OpenJDK 是 在 2007 年由 Sun Corporation(現在的Oracle Corporation) 發布的。是 Oracle JDK 的開源實現版本,以 GPL 協議發布。在 JDK 7 的時候,Sub JDK 就是在 Open JDK 7 的基礎上發布的,只替換了少量的源碼。在 Sun 公司被 Oracle 收購以后,Sun SDK 就被稱為 Oracle JDK。Oracle JDK 是基于 Oracle Binary COde License Agreement 協議。 兩者的區別如下:
Android 和 JDK
說起 Android 和 OpenJDK 的歷史淵源,還是略微復雜。 簡單來說,Android 最開始使用的 Java 是基于 Apache 協議發布的 Harmony,后來由于 Harmony 本身的限制和 Oracle 公司的起訴,從 Android N 以后, Google 開始使用 OpenJDK。 然后我們再稍微展開聊聊。
JVM 和 TCK
Sun 公司最初開發了 Java 語言,同時也開發了 JVM,并且定義了 JVM 規范。這個我們比較清楚,只要基于 JVM 規范開發自己的語言,就可以運行在 JVM 上。但是依照規范開發了語言之后,需要通過 Sun 的 TCK(Technology Compatibility Kit)測試,之后才能成為官方認可的 JVM 語言。
Harmony 和 OpenJDK
基于 JVM 規范,Apache 開發了一個開源免費的 Java 實現 Harmony,并且根據 Apache License v2 發布。但是 Sun 公司并沒有給 Harmony TCK 許可。
在 2009.4.15 Sun 公司發布了 OpenJDK,基于 GNU GPL 發布。同時 Sun 公司規定只有衍生自 OpenJDK 采用的 GPL 協議的開源實現才能運行 OpenJDK 的 TCK。之后 Oracle 收購 Sun 公司以后接管了 OpenJDK。 由于 Apache 的 Harmony 是 Apache 協議,與 OpenJDK 的 GPL 協議不兼容,所以 Harmony 一直沒有得到 TCK 授權。
Android 最開始是采用了 Harmony 作為自己的 Java 類庫,因為 Harmony 使用的 Apache 協議更自由。而由于 Harmony 沒有通過 TCK 認證,也為后來 Oracle 起訴 Google 埋下伏筆。
Oracle 和 Google 關于 JDK 糾紛
后來 Oracle 起訴 Google 主要集中在兩點,一是 Oracle 認為 Google 代碼中使用了 Java 的 37 個 API,二是 Sun 公司前員工在跳槽后為 Android 項目開發時,直接復制了 OpenJDK 中的九行代碼,而 Android 項目并沒有按照 GPL 協議授權,所以復制 OpenJDK 代碼是沒有通過 GPL 授權的。
所以到后來為了解決專利的問題,Android N 以后,Android 開始使用 OpenJDK 替換 Harmony。
以上 Android 和 JDK 參考資料:
juejin.im/entry/5abc5…
zh.wikipedia.org/zh/Android#…
gudong.name/2019/04/05/…
聊了一些關于 Java 的歷史,下面我們看看各個 Java 版本有那些新特性。這里只列出了對開發者影響比較大的一些特性~
Java 8
1. Lambda 和 函數式接口
Lambda 表達式相信不用再過多的介紹,終于在 Java 8 引入了,可以極大的減少代碼量,代碼看起來更清爽。
函數式接口就是有且僅有一個抽象方法,但是可以有多個非抽象方法的接口。可以隱式轉化為 Lambda 表達式。 我們定義一個函數式接口如下:
再定義一個 Class 用來操作 Operation 接口。
class Test {private int operate(int a, int b, Operation operation) {return operation.operation(a, b);} }Test test = new Test(); 復制代碼在 Java 8 之前,我們想要實現 Operation 接口并傳給 Test.operate() 方法使用,我們要定義一個匿名類,實現 Operation 方法。
test.operate(1, 2, new Operation() {public int operation(int a, int b) {return a + b;} }); 復制代碼而使用 Lambda 表達式,我們就可以這樣寫了:
test.operate(1, 2, (a, b) -> a + b); 復制代碼2. 方法引用
通過方法引用,可以使用方法的名字來指向一個方法。使用一對冒號來引 "::" 用方法。 還是以上面的例子來看,我們再添加幾個方法:
interface Operation {int operation(int a, int b); }interface Creater<T> {T get(); }interface TestInt {int cp(Test test1, Test test2); }class Test {public static Test create(Creater<Test> creater) {return creater.get();}private int operate(int a, int b, Operation operation) {return operation.operation(a, b);}private static int add(int a, int b) {return a + b;}private int sub(int a, int b) {return a - b;}public int testM(Test test) {return 0;}public void test(TestInt testInt) {Test t1 = Test.create(Test::new); Test t2 = Test.create(Test::new);testInt.cp(t1, t2);}} 復制代碼那么對應的方法引用有四種: 構造方法引用
使用方式:Class::new
靜態方法引用
使用方式:Class::staticMethod
對象的實例方法引用
使用方式:instance::method
類的實例方法引用
使用方式:Class::method
其實上面三種方法引用都好理解,最后類的實例方法引用,有兩個條件:
3. 接口默認方法和靜態方法
Java 8 新增了接口的默認實現,通過 default 關鍵字表示。同時也可以提供靜態默認方法。
public interface TestInterface {String test();// 接口默認方法default String defaultTest() {return "default";}static String staticTest() {return "static";} } 復制代碼4. 重復注解
Java 8 支持了重復注解。在 Java 8 之前想實現重復注解,需要用一些方法來繞過限制。比如下面的代碼。
Author {String name(); } Authors {Author[] value(); }({(name="a"), (name = "b")}) class Article { } 復制代碼而在 Java 8 中,可以直接用下面的方式。
(Authors.class) Author {String name(); } Authors {Author[] value(); }(name = "a") (name = "b") class Article { } 復制代碼在解析注解的時候,Java 8 也提供了新的 API。
AnnotatedElement.getAnnotationsByType(Class<T>) 復制代碼5. 類型注解
Java 8 之前注解只能用在聲明中,在 Java 8 中,注解可以使用在 任何地方。
(name="a") private Object name = ""; private String author = ((name="a")String) name; 復制代碼6. 更好的類型推斷
Java 8 對于類型推斷做了改進。
比如在 Java 7 中下面的寫法:
在 Java 8 中改進后的寫法,可以自動做類型推斷。
List<String> stringList = new ArrayList<>(); stringList.add("A"); stringList.addAll(Arrays.asList()); 復制代碼7. Optional
Java 8 中新增了 Optional 類用來解決空指針異常。Optional 是一個可以保存 null 的容器對象。通過 isPresent() 方法檢測值是否存在,通過 get() 方法返回對象。
除此之外,Optional 還提供了很多其他有用的方法,具體可以查看文檔。下面是一些示例代碼。
8. Stream
Java 8 中新增的 Stream 類提供了一種新的數據處理方式。這種方式將元素集合看做一種流,在管道中傳輸,經過一系列處理節點,最終輸出結果。
關于 Stream 提供的具體方法,可以參照 API。下面是一些示例代碼。
9. 日期時間 API
Java 8 中新增了日期時間 API 用來加強對日期時間的處理,其中包括了 LocalDate,LocalTime,LocalDateTime,ZonedDateTime 等等,關于 API 可以參照官方文檔以及這篇博客,寫的很詳細。下面是示例代碼。
LocalDate now = LocalDate.now(); System.out.println(now); System.out.println(now.getYear()); System.out.println(now.getMonth()); System.out.println(now.getDayOfMonth());LocalTime localTime = LocalTime.now(); System.out.println(localTime); LocalDateTime localDateTime = now.atTime(localTime); System.out.println(localDateTime); 復制代碼10. Base64 支持
Java 8 標準庫中提供了對 Base 64 編碼的支持。具體 API 見可參照文檔。下面是示例代碼。
String base64 = Base64.getEncoder().encodeToString("aaa".getBytes()); System.out.println(base64); byte[] bytes = Base64.getDecoder().decode(base64); System.out.println(new String(bytes)); 復制代碼11. 并行數組 ParallelSort
Java 8 中提供了對數組的并行操作,包括 parallelSort 等等,具體可參照 API。
Arrays.parallelSort(new int[] {1, 2, 3, 4, 5}); 復制代碼12. 其他新特性
- 對并發的增強 在java.util.concurrent.atomic包中還增加了下面這些類: DoubleAccumulator DoubleAdder LongAccumulator LongAdder
- 提供了新的 Nashorn javascript 引擎
- 提供了 jjs,是一個給予 Nashorn 的命令行工具,可以用來執行 JavaScript 源碼
- 提供了新的類依賴分析工具 jdeps
- JVM 的新特性 JVM內存永久區已經被metaspace替換(JEP 122)。JVM參數 -XX:PermSize 和 –XX:MaxPermSize被XX:MetaSpaceSize 和 -XX:MaxMetaspaceSize代替。
可以看到,Java 8 整體上的改進是很大的,最重要的是引入 Lambda 表達式,簡化代碼。
其他一些改進可參照 www.oracle.com/technetwork…
Java 9
1. Jigsaw 模塊系統
在 Java 9 以前,打包和依賴都是基于 JAR 包進行的。JRE 中包含了 rt.jar,將近 63M,也就是說要運行一個簡單的 Hello World,也需要依賴這么大的 jar 包。在 Java 9 中提出的模塊化系統,對這點進行了改善。 關于模塊化系統具體可以看看這篇文章。
2. JShell REPL
Java 9 提供了交互式解釋器。有了 JShell 以后,Java 終于可以像 Python,Node.js 一樣在 Shell 中運行一些代碼并直接得出結果了。
3. 私有接口方法,接口中使用私有方法
Java 9 中可以在接口中定義私有方法。示例代碼如下:
public interface TestInterface {String test();// 接口默認方法default String defaultTest() {pmethod();return "default";}private String pmethod() {System.out.println("private method in interface");return "private";} } 復制代碼4. 集合不可變實例工廠方法
在以前,我們想要創建一個不可變的集合,需要先創建一個可變集合,然后使用 unmodifiableSet 創建不可變集合。代碼如下:
Set<String> set = new HashSet<>(); set.add("A"); set.add("B"); set.add("C");set = Collections.unmodifiableSet(set); System.out.println(set); 復制代碼Java 9 中提供了新的 API 用來創建不可變集合。
List<String> list = List.of("A", "B", "C"); Set<String> set = Set.of("A", "B", "C"); Map<String, String> map = Map.of("KA", "VA", "KB", "VB"); 復制代碼5. 改進 try-with-resources
Java 9 中不需要在 try 中額外定義一個變量。Java 9 之前需要這樣使用 try-with-resources:
InputStream inputStream = new StringBufferInputStream("a"); try (InputStream in = inputStream) {in.read(); } catch (IOException e) {e.printStackTrace(); } 復制代碼在 Java 9 中可以直接使用 inputStream 變量,不需要再額外定義新的變量了。
InputStream inputStream = new StringBufferInputStream("a"); try (inputStream) {inputStream.read(); } catch (IOException e) {e.printStackTrace(); } 復制代碼6. 多版本兼容 jar 包
Java 9 中支持在同一個 JAR 中維護不同版本的 Java 類和資源。
7. 增強了 Stream,Optional,Process API
8. 新增 HTTP2 Client
9. 增強 Javadoc,增加了 HTML 5 文檔的輸出,并且增加了搜索功能
10. 增強 @Deprecated
對 Deprecated 新增了 since 和 forRemoval 屬性
11. 增強了鉆石操作符 "<>",可以在 匿名內部類中使用了。
在 Java 9 之前,內部匿名類需要指定泛型類型,如下:
Handler<? extends Number> intHandler1 = new Handler<Number>(2) { } 復制代碼而在 Java 9 中,可以自動做類型推導,如下:
Handler<? extends Number> intHandler1 = new Handler<>(2) { } 復制代碼12. 多分辨率圖像 API:定義多分辨率圖像API,開發者可以很容易的操作和展示不同分辨率的圖像了。
13. 改進的 CompletableFuture API
CompletableFuture 類的異步機制可以在 ProcessHandle.onExit 方法退出時執行操作。
其他一些改進可參照 docs.oracle.com/javase/9/wh…
Java 10
1. 新增局部類型推斷 var
var a = "aa"; System.out.println(a); 復制代碼var 關鍵字目前只能用于局部變量以及 for 循環變量聲明中。
2. 刪除工具 javah
從JDK中移除了 javah 工具,使用 javac -h 代替。
3. 統一的垃圾回收接口,改進了 GC 和其他內務管理
其他特性
-
ThreadLocal 握手交互
JDK 10 引入一種在線程上執行回調的新方法,很方便的停止單個線程而不是停止全部線程或者一個都不停。 -
基于Java的實驗性JIT編譯器
Java 10 開啟了 Java JIT編譯器 Graal,用作Linux / x64平臺上的實驗性JIT編譯器。 -
提供默認的 CA 根證書
-
將 JDK 生態整合到單個倉庫
此JEP的主要目標是執行一些內存管理,并將JDK生態的眾多存儲庫組合到一個存儲庫中。
其他一些改進可以參照 www.oracle.com/technetwork…
Java 11
1. Lambda 中使用 var
(var x, var y) -> x.process(y) 復制代碼2. 字符串 API 增強
Java 11 新增了 一系列字符串處理方法,例如:
// 判斷字符串是否為空白 " ".isBlank(); " Javastack ".stripTrailing(); // " Javastack" " Javastack ".stripLeading(); // "Javastack " 復制代碼3. 標準化 HttpClient API
4. java 直接編譯并運行,省去先 javac 編譯生成 class 再運行的步驟
5. 增加對 TLS 1.3 的支持
其他一些改進可以參照 www.oracle.com/technetwork…
Java 12
switch 表達式
Java 12 以后,switch 不僅可以作為語句,也可以作為表達式。
private String switchTest(int i) {return switch (i) {case 1 -> "1";default -> "0";}; } 復制代碼其他一些改進可以參照 www.oracle.com/technetwork…
總結
參考資料
Java8
ifeve.com/java-8-feat…
juejin.im/post/5ae6bf…
wizardforcel.gitbooks.io/java8-tutor…
www.oracle.com/technetwork…
www.oracle.com/technetwork…
Java9
www.runoob.com/java/java9-…
docs.oracle.com/javase/9/wh…
www.twle.cn/c/yufei/jav…
Java10
baijiahao.baidu.com/s?id=159443…
blog.csdn.net/visant/arti…
www.oracle.com/technetwork…
Java 11
openjdk.java.net/projects/jd…
www.ctolib.com/topics-1351…
Java 12
zhuanlan.zhihu.com/p/59798800
其他
www.baeldung.com/oracle-jdk-…
zh.wikipedia.org/wiki/Java版本…
www.zhihu.com/question/19…
juejin.im/post/5ca1c7…
gudong.name/2019/04/05/…
歡迎關注下面賬號,獲取最新技術文章:
Github
掘金
知乎
總結
以上是生活随笔為你收集整理的聊聊 Java8 以后各个版本的新特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信公众号基础功能搭建怎么弄_怎么做一个
- 下一篇: 浏览器截图快捷键在哪里