小貓們,大家好))所以,今天已經是 2020 年了,距離 Java 14 的發布已經所剩無幾了。你應該期待 3 月 17 日的完成版本,事後我們會分析其中有哪些新鮮有趣的內容,但今天我想回顧一下以前的 Java 版本。他們為我們帶來了什麼新鮮事?我們來看看吧。讓我們從 Java 8 開始回顧,因為它仍然非常相關並且在大多數專案中使用。 在此之前,每 3-5 年發布一次新版本,但最近 Oracle 採取了不同的做法——「每六個月發布一個新 Java」。因此,每六個月我們就會看到功能的發布。不管是好是壞,每個人的看法都不一樣。比如說,我就不太喜歡這個,因為新版本沒有太多新功能,但同時,版本卻如雨後春筍般生長。我在一個Java 8 的專案上眨了幾下眼,Java 16 已經發布了(但當它很少出現時,新功能就會累積起來,最後這個事件就像假期一樣期待已久:每個人都在討論新的好東西,你不能錯過它)。那麼就讓我們開始吧!
爪哇8
功能介面
這是什麼?函數式介面是包含一個未實作(抽象)方法的介面。 @FunctionalInterface是一個可選註釋,放置在此類介面之上。需要檢查它是否滿足功能介面的要求(只有一個抽象方法)。但與往常一樣,我們有一些警告:預設方法和靜態方法不符合這些要求。因此,可以有多個這樣的方法+一個抽象方法,並且該介面將是函數式的。它也可能包含 Object 類別的方法,這些方法不會影響介面的功能定義。我將添加一些關於預設和靜態方法的內容:-
具有default修飾符的方法可讓您向介面新增方法,而不會破壞其現有實作。
public interface Something { default void someMethod { System.out.println("Some text......"); } }
是的,是的,我們將實作的方法加入到介面中,並且在實作這個方法時,不能覆寫它,而是將其作為繼承的方法使用。但是,如果一個類別使用給定的方法實現了兩個接口,我們將會遇到編譯錯誤,並且如果它實現了接口並繼承了具有某個相同方法的類,則父類方法將與接口方法重疊,並且異常將不起作用。
-
介面中的靜態方法與類別中的靜態方法的工作方式相同。不要忘記:您不能繼承靜態方法,就像您不能從後代類別呼叫靜態方法一樣。
-
Consumer - 接受 T 類型的參數,不傳回任何內容 (void)。
例子:
void someMethod(T t);
-
供應商 - 不接受任何輸入,但傳回一些值 T。
例子:
T someMethod();
-
函數 - 將 T 型別的參數當作輸入,傳回 R 類型的值。
例子:
R someMethod(T t);
-
UnaryOperator - 接受 T 參數並傳回 T 類型的值。
例子:
T someMethod(T t);
謂詞 - 採用某個值 T 作為參數,並傳回布林值。
例子:boolean someMethod(T t);
溪流
流是一種以函數式方式處理資料結構的方法。通常這些是集合(但您可以在其他不太常見的情況下使用它們)。用更容易理解的語言來說,Stream 是一種資料流,我們處理它時就像同時處理所有資料一樣,而不是像 for-each 那樣使用蠻力。讓我們來看一個小例子。假設我們有一組要過濾的數字(小於 50),增加 5,並將剩餘數字中的前 4 個數字輸出到控制台。早些時候我們會如何做:List<Integer> list = Arrays.asList(46, 34, 24, 93, 91, 1, 34, 94);
int count = 0;
for (int x : list) {
if (x >= 50) continue;
x += 5;
count++;
if (count > 4) break;
System.out.print(x);
}
看起來程式碼不多,邏輯已經有點混亂了。讓我們看看使用串流會是什麼樣子:
Stream.of(46, 34, 24, 93, 91, 1, 34, 94)
.filter(x -> x < 50)
.map(x -> x + 5)
.limit(4)
.forEach(System.out::print);
串流透過減少程式碼量並使其更具可讀性,極大地簡化了生活。對於那些想要更詳細地深入研究這個主題的人,這裡有一篇關於這個主題的好(我甚至可以說很棒)的文章。
拉姆達
也許最重要和期待已久的功能是 lambda 的出現。 什麼是拉姆達?這是一個可以傳遞到不同位置的程式碼區塊,因此可以根據需要多次執行。聽起來很令人困惑,不是嗎?簡單地說,使用 lambda,您可以實作函數式介面的方法(匿名類別的實作):Runnable runnable = () -> { System.out.println("I'm running !");};
new Thread(runnable).start();
我們快速實作了 run() 方法,沒有不必要的繁文縟節。是的:Runnable 是一個函數式介面。我在處理流程時也會使用 lambda(如上面的流程範例)。我們不會太深,因為我們可以深入得很深,我會留下幾個鏈接,以便那些仍然是挖掘者的人可以深入挖掘:
- Habré 上有關 Java 8 中 lambda 表達式的文章
- Alexander Kosarev 部落格上有關 Java 中 lambda 表達式的文章
foreach
Java 8 有一個新的 foreach,可以像流一樣處理資料流。這是一個例子:List<Integer> someList = Arrays.asList(1, 3, 5, 7, 9);
someList.forEach(x -> System.out.println(x));
(類似於 someList.stream().foreach(...))
方法參考
引用方法是一種新的、有用的語法,旨在透過 :: 引用 Java 類別或物件的現有方法或建構子。方法引用有四種類型:-
設計師連結:
SomeObject obj = SomeObject::new
-
靜態方法參考:
SomeObject::someStaticMethod
-
對某種類型物件的非靜態方法的引用:
SomeObject::someMethod
-
對特定物件的常規(非靜態)方法的引用
obj::someMethod
someList.stream()
.map(String::toUpperCase)
.forEach(System.out::println);
對於那些想了解有關參考方法的更多資訊的人:
API時間
有一個用於處理日期和時間的新庫 - java.time。 新的 API 與任何 Joda-Time 類似。該 API 最重要的部分是:- LocalDate是一個具體日期,例如 - 2010-01-09;
- LocalTime - 考慮時區的時間 - 19:45:55(類似 LocalDate);
- LocalDateTime - 組合 LocalDate + LocalTime - 2020-01-04 15:37:47;
- ZoneId - 代表時區;
- 時鐘- 使用此類型您可以存取當前時間和日期。
- Java 和時間:關於哈布雷的第一部分和第二部分
- Java 8 中的日期/時間 API 簡介
選修的
這是java.util套件中的一個新類別,它是一個值包裝器,其技巧是它也可以安全地包含null。接收可選: 如果我們Optional<String> someOptional = Optional.of("Something");
在Optional.of中傳遞null,我們將得到我們最喜歡的NullPointerException。對於這種情況,他們使用: Optional<String> someOptional = Optional.ofNullable("Something");
- 在這種方法中,您不必擔心 null。接下來,建立一個原本為空的Optional: Optional<String> someOptional = Optional.empty();
要檢查它是否為空,請使用: someOptional.isPresent();
將會向我們傳回true或false。如果有值則執行某個操作,如果沒有值則不執行任何操作:如果 someOptional.ifPresent(System.out::println);
Optional為空則傳回傳遞的值的反向方法(有點備份計劃): System.out.println(someOptional.orElse("Some default content"));
您可以繼續非常非常長的時間(幸運的是, Optional 慷慨地添加了方法),但我們不會詳細討論這一點。我最好為初學者留下幾個連結:
我們回顧了 Java 8 中最著名的創新——這還不是全部。如果你想了解更多,那麼我給你留下了這個:
- Java 8 的功能:JavaRush 終極指南 -第 1 部分和第 2 部分;
- Java 8 中關於 Habré 的新功能;
- 人們不談論的 10 個 Java 8 特性;
- Java 8 教程。
爪哇9
因此,2017 年 9 月 21 日,全世界看到了 JDK 9。這個 Java 9 有豐富的功能。雖然沒有新的語言概念,但新的 API 和診斷命令肯定會引起開發人員的興趣。JShell(REPL - 讀取-評估-列印循環)
這是互動式控制台的 Java 實現,用於測試功能並在控制台中使用不同的構造,例如介面、類別、枚舉、運算符等。要啟動JShell,您只需在終端機中編寫 jshell 即可。然後我們可以編寫任何我們想像的內容: 使用 JShell,您可以建立頂級方法並在同一會話中使用它們。這些方法的工作方式與靜態方法一樣,只是可以省略static關鍵字。請閱讀Java 9 REPL (JShell) 手冊以了解更多資訊。私人的
從 Java 版本 9 開始,我們有機會在介面中使用私有方法(預設方法和靜態方法,因為由於存取權限不足,我們根本無法覆寫其他方法)。private static void someMethod(){}
try-with-resources
處理 Try-With-Resources 異常的能力已升級:
BufferedReader reader = new BufferedReader(new FileReader("....."));
try (reader2) {
....
}
模組化(拼圖)
模組是一組相關的套件和資源以及新的模組描述符檔案。這種方法用於放鬆代碼的耦合。松耦合是程式碼可維護性和可擴展性的關鍵因素。模組化在不同層面上實現:- 程式設計語言.
- 虛擬機。
- 標準java API。
不可變集合
在Java 9中,可以用一行創建和填充集合,同時使其不可變(以前,要創建不可變集合,我們需要創建一個集合,用數據填充它,然後調用一個方法,例如,集合.不可修改列表)。這種創作的例子:List someList = List.of("first","second","third");
其他創新:
- 擴展可選(添加新方法);
- ProcessHandle 和 ProcessHandle 介面似乎用來控製作業系統的操作;
- G1——預設垃圾收集器;
- 支援 HTTP/2 協定和 WebSocket 的 HTTP 用戶端;
- 擴展流;
- 新增了 Reactive Streams API 框架(用於反應式程式設計);
爪哇10
因此,在 Java 9 發布六個月後,即 2018 年 3 月(我記得就像昨天一樣),Java 10 出現了。變數
現在我們不必提供資料類型。我們將訊息標記為 var,編譯器根據右側初始化程序的類型來確定訊息的類型。此功能僅適用於具有初始值設定項目的局部變數:它不能用於方法參數、傳回類型等,因為沒有能夠定義類型的初始值設定項。範例 var(對於 String 類型):var message = "Some message…..";
System.out.println(message);
var 不是關鍵字:它本質上是一個保留的類型名稱,就像int一樣。var的好處很大:類型聲明佔用了很多注意力,卻沒有帶來任何好處,而且這個功能會節省時間。但同時,如果從一長串方法中獲取變量,程式碼的可讀性就會降低,因為我們立即不清楚那裡是什麼類型的物件。獻給那些想要更熟悉此功能的人:
JIT 編譯器 (GraalVM)
言歸正傳,讓我提醒您,當您執行 javac 命令時,Java 應用程式將從 Java 程式碼編譯為 JVM 字節碼,這是應用程式的二進位表示法。但常規電腦處理器不能簡單地執行 JVM 字節碼。為了讓 JVM 程式正常運作,您需要另一個編譯器來編譯該字節碼,將其轉換為處理器已經能夠使用的機器碼。與 javac 相比,此編譯器要複雜得多,但也會產生更高品質的機器碼。目前,OpenJDK包含 HotSpot 虛擬機,而該虛擬機又有兩個主要的 JIT 編譯器。第一個是 C1(客戶端編譯器),專為更高速度的操作而設計,但程式碼最佳化受到影響。第二個是C2(伺服器編譯器)。執行速度受到影響,但程式碼更加優化。什麼時候使用哪一個?C1 非常適合桌面應用程序,因為長時間的 JIT 暫停是不受歡迎的,而 C2 非常適合長時間運行的伺服器程序,因為在編譯上花費更多時間是可以忍受的。 多層次編譯是編譯首先經過C1,結果再經過C2(用於更大程度的最佳化)。 GraalVM是一個為了完全取代 HotSpot 而創建的專案。我們可以將 Graal 視為幾個相關專案:一個新的 HotSpot JIT 編譯器和一個新的多語言虛擬機器。這個 JIT 編譯器的獨特之處在於它是用 Java 寫的。Graal編譯器的優點是安全,即不會崩潰,不會出現異常,不會記憶體洩漏。我們還將擁有良好的 IDE 支持,並且我們將能夠使用調試器、分析器或其他方便的工具。此外,編譯器很可能獨立於 HotSpot,而且它將能夠創建自身更快的 JIT 編譯版本。 對於挖土機:平行G1
G1 垃圾收集器確實很酷,這是毫無疑問的,但它也有一個弱點:它執行單執行緒完整 GC 週期。當您需要使用所有硬體功能來尋找未使用的物件時,我們僅限於單一執行緒。Java 10 修正了這個問題。現在 GC 現在可以使用我們新增到其中的所有資源(也就是說,它變成了多執行緒)。為了實現這一目標,語言開發人員改進了主要來源與 GC 的隔離,為 GC 創建了一個漂亮、乾淨的介面。這個可愛的開發者 OpenJDK 必須專門清理程式碼中的轉儲,以便不僅盡可能簡化新 GC 的創建,而且還可以快速停用程式集中不必要的 GC。成功的主要標準之一是在所有這些改進之後運行速度沒有下降。 我們還要看一下: 其他創新:- 引入了乾淨的垃圾收集器介面。這改善了原始程式碼與不同垃圾收集器的隔離,從而可以快速、輕鬆地整合替代收集器;
- 將 JDK 來源合併到一個儲存庫中;
- Collections 收到了一個新方法 - copyOf (Collection),它會傳回此集合的不可變副本;
- Optional(及其變體)有一個新方法.orElseThrow();
- 從現在開始,JVM 知道它們正在 Docker 容器中運行,並將取得特定於容器的配置,而不是查詢作業系統本身。
- Java 10 指南
- Java 開發人員應該了解的 10 個 JDK 10 功能
- Java 10 的新增功能:第一部分與第二部分
GO TO FULL VERSION