JavaRush /Java Blog /Random-TW /從 8 到 13:Java 版本的完整概述。第1部分

從 8 到 13:Java 版本的完整概述。第1部分

在 Random-TW 群組發布
小貓們,大家好))所以,今天已經是 2020 年了,距離 Java 14 的發布已經所剩無幾了。你應該期待 3 月 17 日的完成版本,事後我們會分析其中有哪些新鮮有趣的內容,但今天我想回顧一下以前的 Java 版本。他們為我們帶來了什麼新鮮事?我們來看看吧。讓我們從 Java 8 開始回顧,因為它仍然非常相關並且在大多數專案中使用。 從 8 到 13:Java 版本的完整概述。 第 1 - 1 部分在此之前,每 3-5 年發布一次新版本,但最近 Oracle 採取了不同的做法——「每六個月發布一個新 Java」。因此,每六個月我們就會看到功能的發布。不管是好是壞,每個人的看法都不一樣。比如說,我就不太喜歡這個,因為新版本沒有太多新功能,但同時,版本卻如雨後春筍般生長。我在一個Java 8 的專案上眨了幾下眼,Java 16 已經發布了(但當它很少出現時,新功能就會累積起來,最後這個事件就像假期一樣期待已久:每個人都在討論新的好東西,你不能錯過它)。那麼就讓我們開始吧!

爪哇8

功能介面

這是什麼?函數式介面是包含一個未實作(抽象)方法的介面。 @FunctionalInterface是一個可選註釋,放置在此類介面之上。需要檢查它是否滿足功能介面的要求(只有一個抽象方法)。但與往常一樣,我們有一些警告:預設方法和靜態方法不符合這些要求。因此,可以有多個這樣的方法+一個抽象方法,並且該介面將是函數式的。它也可能包含 Object 類別的方法,這些方法不會影響介面的功能定義。我將添加一些關於預設和靜態方法的內容:
  1. 具有default修飾符的方法可讓您向介面新增方法,而不會破壞其現有實作。

    public interface Something {
      default void someMethod {
          System.out.println("Some text......");
      }
    }

    是的,是的,我們將實作的方法加入到介面中,並且在實作這個方法時,不能覆寫它,而是將其作為繼承的方法使用。但是,如果一個類別使用給定的方法實現了兩個接口,我們將會遇到編譯錯誤,並且如果它實現了接口並繼承了具有某個相同方法的類,則父類方法將與接口方法重疊,並且異常將不起作用。

  2. 介面中的靜態方法與類別中的靜態方法的工作方式相同。不要忘記:您不能繼承靜態方法,就像您不能從後代類別呼叫靜態方法一樣。

那麼,再多說幾句關於函數式介面的內容,然後讓我們繼續。以下是主要的金融機構清單(其餘是其品種):

    謂詞 - 採用某個值 T 作為參數,並傳回布林值。

    例子:boolean someMethod(T t);

  • Consumer - 接受 T 類型的參數,不傳回任何內容 (void)。

    例子:void someMethod(T t);

  • 供應商 - 不接受任何輸入,但傳回一些值 T。

    例子:T someMethod();

  • 函數 - 將 T 型別的參數當作輸入,傳回 R 類型的值。

    例子:R someMethod(T t);

  • UnaryOperator - 接受 T 參數並傳回 T 類型的值。

    例子:T 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(如上面的流程範例)。我們不會太深,因為我們可以深入得很深,我會留下幾個鏈接,以便那些仍然是挖掘者的人可以深入挖掘:

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 類別或物件的現有方法或建構子。方法引用有四種類型:
  1. 設計師連結:

    SomeObject obj = SomeObject::new

  2. 靜態方法參考:

    SomeObject::someStaticMethod

  3. 對某種類型物件的非靜態方法的引用:

    SomeObject::someMethod

  4. 對特定物件的常規(非靜態)方法的引用

    obj::someMethod

通常,在流中使用方法引用而不是 lambda(引用方法比 lambda 更快,但可讀性較差)。
someList.stream()

        .map(String::toUpperCase)

      .forEach(System.out::println);
對於那些想了解有關參考方法的更多資訊的人:

API時間

有一個用於處理日期和時間的新庫 - java.time。 從 8 到 13:Java 版本的完整概述。 第 1 - 2 部分新的 API 與任何 Joda-Time 類似。該 API 最重要的部分是:
  • LocalDate是一個具體日期,例如 - 2010-01-09;
  • LocalTime - 考慮時區的時間 - 19:45:55(類似 LocalDate);
  • LocalDateTime - 組合 LocalDate + LocalTime - 2020-01-04 15:37:47;
  • ZoneId - 代表時區;
  • 時鐘- 使用此類型您可以存取當前時間和日期。
這裡有幾篇關於這個主題的非常有趣的文章:

選修的

這是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 中最著名的創新——這還不是全部。如果你想了解更多,那麼我給你留下了這個:

爪哇9

因此,2017 年 9 月 21 日,全世界看到了 JDK 9。這個 Java 9 有豐富的功能。雖然沒有新的語言概念,但新的 API 和診斷命令肯定會引起開發人員的興趣。 從 8 到 13:Java 版本的完整概述。 第 1 - 4 部分

JShell(REPL - 讀取-評估-列印循環)

這是互動式控制台的 Java 實現,用於測試功能並在控制台中使用不同的構造,例如介面、類別、枚舉、運算符等。要啟動JShell,您只需在終端機中編寫 jshell 即可。然後我們可以編寫任何我們想像的內容: 從 8 到 13:Java 版本的完整概述。 第 1 - 5 部分使用 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) {
  ....
}

模組化(拼圖

模組是一組相關的套件和資源以及新的模組描述符檔案。這種方法用於放鬆代碼的耦合。松耦合是程式碼可維護性和可擴展性的關鍵因素。模組化在不同層面上實現:
  1. 程式設計語言.
  2. 虛擬機。
  3. 標準java API。
JDK 9 隨附 92 個模組:我們可以使用它們或建立自己的模組。以下是一些可以更深入了解的連結:

不可變集合

在Java 9中,可以用一行創建和填充集合,同時使其不可變(以前,要創建不可變集合,我們需要創建一個集合,用數據填充它,然後調用一個方法,例如,集合.不可修改列表)。這種創作的例子: List someList = List.of("first","second","third");

其他創新:

  • 擴展可選(添加新方法);
  • ProcessHandle 和 ProcessHandle 介面似乎用來控製作業系統的操作;
  • G1——預設垃圾收集器;
  • 支援 HTTP/2 協定和 WebSocket 的 HTTP 用戶端;
  • 擴展流;
  • 新增了 Reactive Streams API 框架(用於反應式程式設計);
為了更完整地沉浸在 Java 9 中,我建議您閱讀:

爪哇10

因此,在 Java 9 發布六個月後,即 2018 年 3 月(我記得就像昨天一樣),Java 10 出現了。 從 8 到 13:Java 版本的完整概述。 第 1 - 6 部分

變數

現在我們不必提供資料類型。我們將訊息標記為 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。成功的主要標準之一是在所有這些改進之後運行速度沒有下降。 我們還要看一下: 其他創新:
  1. 引入了乾淨的垃圾收集器介面。這改善了原始程式碼與不同垃圾收集器的隔離,從而可以快速、輕鬆地整合替代收集器;
  2. 將 JDK 來源合併到一個儲存庫中;
  3. Collections 收到了一個新方法 - copyOf (Collection),它會傳回此集合的不可變副本;
  4. Optional(及其變體)有一個新方法.orElseThrow()
  5. 從現在開始,JVM 知道它們正在 Docker 容器中運行,並將取得特定於容器的配置,而不是查詢作業系統本身。
以下是一些更詳細介紹 Java 10 的資料: 我曾經對 Java 的某些版本被稱為 1.x 這一事實感到非常困惑。我想澄清一下:Java 9 之前的版本只是有不同的命名方案。例如,Java 8 也可以稱為1.8、Java 5 - 1.5等。現在我們看到,隨著從 Java 9 過渡到版本,命名方案也發生了變化,Java 版本不再以 1.x 為前綴。第一部分到此結束:我們回顧了 java 8-10 的新的有趣特性。讓我們在下一篇文章中繼續了解最新的情況。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION