是時候升級java11了」 jdk11優勢和jdk選擇

從2019年1月份開始,Oracle JDK 開始對 Java SE 8 之後的版本開始進行商用收費,確切的說是 8u201/202 之後的版本。如果你用 Java 開發的功能如果是用作商業用途的,如果還不想花錢購買的話,能免費使用的最新版本是 8u201/202。當然如果是個人客戶端或者個人開發者可以免費試用 Oracle JDK 所有的版本。
Java11 的性能提升
僅通過切換到 Java 11 就有 16% 的改進,這種改進可能是因爲 Java 10 中引入了 JEP 307: Parallel Full GC for G1。
詳情請見Java 11 究竟比 8 快了多少?看看這個基準測試
從java 8到java 11變化一覽
說明:這裏面我們不會介紹全部特性,只會列舉部分作爲開發者最關心的變化。
緊湊型的字符串
從Java 9開始 String 數據承載由 char[] 改爲 byte[] 緊湊的字符串,在很多時候只包含Latin-1裏的字符,這些字符可節省一半內存。
增強api
1.字符串增強 @since 11
// 判斷字符串是否爲空白
" ".isBlank(); // true
// 去除首尾空格
" Hello Java11 ".strip(); // “Hello Java11”
// 去除尾部空格
" Hello Java11 “.stripTrailing(); // " Hello Java11”
// 去除首部空格
" Hello Java11 ".stripLeading(); // "Hello Java11 "
// 複製字符串
“Java11”.repeat(3); // “Java11Java11Java11”
// 行數統計
“A\nB\nC”.lines().count(); // 3
複製代碼2.集合增強
從Java 9 開始,jdk裏面就爲集合(List、Set、Map)增加了of和copyOf方法。它們用來創建不可變集合。

of() @since 9
copyOf() @since 10

示例一:
var list = List.of(“Java”, “Python”, “C”); //不可變集合
var copy = List.copyOf(list); //copyOf判斷是否是不可變集合類型,如果是直接返回
System.out.println(list == copy); // true
var list = new ArrayList(); // 這裏返回正常的集合
var copy = List.copyOf(list); // 這裏返回一個不可變集合
System.out.println(list == copy); // false
複製代碼示例二:
var set = Set.of(“Java”, “Python”, “C”);
var copy = Set.copyOf(set);
System.out.println(set == copy); // true
var set1 = new HashSet();
var copy1 = List.copyOf(set1);
System.out.println(set1 == copy1); // false
複製代碼示例三:
var map = Map.of(“Java”, 1, “Python”, 2, “C”, 3);
var copy = Map.copyOf(map);
System.out.println(map == copy); // true
var map1 = new HashMap<String, Integer>();
var copy1 = Map.copyOf(map1);
System.out.println(map1 == copy1); // false
複製代碼注意:使用 of 和 copyOf 創建的集合爲不可變集合,不能進行添加、刪除、替換、排序等操作,不然會報java.lang.UnsupportedOperationException異常,使用Set.of()不能出現重複元素、Map.of()不能出現重複key,否則回報java.lang.IllegalArgumentException。。
3.Stream增強 @since 9
Stream是Java 8 中的特性,在Java 9 中爲其新增了4個方法:
3.1 ofNullable(T t)
此方法可以接收null來創建一個空流
// 以前
Stream.of(null); //報錯
// 現在
Stream.ofNullable(null);
複製代碼3.2 takeWhile(Predicate<? super T> predicate)
此方法根據Predicate接口來判斷如果爲true就 取出 來生成一個新的流,只要碰到false就終止,不管後邊的元素是否符合條件。
Stream integerStream = Stream.of(6, 10, 11, 15, 20);
Stream takeWhile = integerStream.takeWhile(t -> t % 2 == 0);
takeWhile.forEach(System.out::println); // 6,10
複製代碼3.3 dropWhile(Predicate<? super T> predicate)
此方法根據Predicate接口來判斷如果爲true就 丟棄 來生成一個新的流,只要碰到false就終止,不管後邊的元素是否符合條件。
Stream integerStream = Stream.of(6, 10, 11, 15, 20);
Stream takeWhile = integerStream.dropWhile(t -> t % 2 == 0);
takeWhile.forEach(System.out::println); //11,15,20
複製代碼3.4 iterate重載
以前使用iterate方法生成無限流需要配合limit進行截斷
Stream limit = Stream.iterate(1, i -> i + 1).limit(5);
limit.forEach(System.out::println); //1,2,3,4,5
複製代碼現在重載後這個方法增加了個判斷參數
Stream iterate = Stream.iterate(1, i -> i <= 5, i -> i + 1);
iterate.forEach(System.out::println); //1,2,3,4,5
複製代碼4.Optional增強 @since 9
4.1 stream()
如果爲空返回一個空流,如果不爲空將Optional的值轉成一個流。
//返回Optional值的流
Stream stream = Optional.of(“Java 11”).stream();
stream.forEach(System.out::println); // Java 11

//返回空流
Stream stream = Optional.ofNullable(null).stream();
stream.forEach(System.out::println); //
複製代碼4.2 ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
個人感覺這個方法就是結合isPresent()對Else的增強,ifPresentOrElse 方法的用途是,如果一個 Optional 包含值,則對其包含的值調用函數 action,即 action.accept(value),這與 ifPresent 一致;與 ifPresent 方法的區別在於,ifPresentOrElse 還有第二個參數 emptyAction —— 如果 Optional 不包含值,那麼 ifPresentOrElse 便會調用 emptyAction,即 emptyAction.run()。
Optional optional = Optional.of(1);
optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() ->
System.out.println(“Not Present.”)); //Value: 1

optional = Optional.empty();
optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() ->
System.out.println(“Not Present.”)); //Not Present.
複製代碼4.3 or(Supplier<? extends Optional<? extends T>> supplier)
Optional optional1 = Optional.of(“Java”);
Supplier<Optional> supplierString = () -> Optional.of(“Not Present”);
optional1 = optional1.or( supplierString);
optional1.ifPresent( x -> System.out.println("Value: " + x)); //Value: Java
optional1 = Optional.empty();
optional1 = optional1.or( supplierString);
optional1.ifPresent( x -> System.out.println("Value: " + x)); //Value: Not Present
複製代碼5.InputStream增強 @since 9
String lxs = “java”;
try (var inputStream = new ByteArrayInputStream(lxs.getBytes());
var outputStream = new ByteArrayOutputStream()) {
inputStream.transferTo(outputStream);
System.out.println(outputStream); //java
}
複製代碼HTTP Client API
改api支持同步和異步兩種方式,下面是兩種方式的示例:
var request = HttpRequest.newBuilder()
.uri(URI.create(“https://www.baidu.com/”))
.build();
var client = HttpClient.newHttpClient();
// 同步
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
// 異步
CompletableFuture<HttpResponse> sendAsync = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
//這裏會阻塞
HttpResponse response1 = sendAsync.get();
System.out.println(response1.body());
複製代碼移除內容

com.sun.awt.AWTUtilities。
sun.misc.Unsafe.defineClass 使用java.lang.invoke.MethodHandles.Lookup.defineClass來替代。
Thread.destroy() 以及 Thread.stop(Throwable) 方法。
sun.nio.ch.disableSystemWideOverlappingFileLockCheck 屬性。
sun.locale.formatasdefault 屬性。
jdk snmp 模塊。
javafx,openjdk 是從java10版本就移除了,oracle java10還尚未移除javafx ,而java11版本將javafx也移除了。
Java Mission Control,從JDK中移除之後,需要自己單獨下載。
Root Certificates :Baltimore Cybertrust Code Signing CA,SECOM ,AOL and Swisscom。
在java11中將java9標記廢棄的Java EE及CORBA模塊移除掉。

完全支持Linux容器(包括docker)
許多運行在Java虛擬機中的應用程序(包括Apache Spark和Kafka等數據服務以及傳統的企業應用程序)都可以在Docker容器中運行。但是在Docker容器中運行Java應用程序一直存在一個問題,那就是在容器中運行JVM程序在設置內存大小和CPU使用率後,會導致應用程序的性能下降。這是因爲Java應用程序沒有意識到它正在容器中運行。隨着Java 10的發佈,這個問題總算得以解決,JVM現在可以識別由容器控制組(cgroups)設置的約束。可以在容器中使用內存和CPU約束來直接管理Java應用程序,其中包括:

遵守容器中設置的內存限制
在容器中設置可用的CPU
在容器中設置CPU約束

JDK推薦
由於 Java 11 開始,Oracle 提供的是付費支持的商業版本。筆者在這更加推薦使用亞馬遜的 Corretto,Corretto 採用 GPL 協議。
Corretto的長期支持(LTS)包括Corretto 8的性能增強和安全更新,至少在2023年6月之前免費提供。 更新計劃每季度發佈一次。
亞馬遜將爲Corretto 11提供LTS的季度更新,至少持續到2024年8月。

發佈了15 篇原創文章 · 獲贊 0 · 訪問量 545
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章