趕快看看Java11,不然你就out了 [復制鏈接]

2019-11-6 10:06
有事在發生 閱讀:158 評論:0 贊:0
Tag:  Java11

前言

更新的太快了,都學不過來了,最近了解一些Java8以后的一些特性,寫下來希望對大家有幫助。

為什么選擇Java11

  • 容器環境支持,GC等領域的增強。
  • 進行了瘦身,更輕量級,安裝包體積小。
  • JDK11 是一個長期支持版。

特性介紹

由于直接從Java8跨越到Java11,所以特性介紹就把Java9-Java11的部分特性一起介紹一下。

Jshell @since 9

Jshell在Java9中就被提出來了,可以直接在終端寫Java程序,回車就可以執行。Jshell默認會導入下面的一些包,所以在Jshell環境中這些包的內容都是可以使用的。

import java.lang.*; 
import java.io.*;
import java.math.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.prefs.*;
import java.util.regex.*;
import java.util.stream.*;

1.什么是Jshell?

Jshell是在 Java 9 中引入的。它提供了一個交互式 shell,用于快速原型、調試、學習 Java 及 Java API,所有這些都不需要 public static void main 方法,也不需要在執行之前編譯代碼。

2.Jshell的使用

打開終端,鍵入jshell進入jshell環境,然后輸入/help intro可以查看Jshell的介紹。

 [email protected]  ~  jshell
| 歡迎使用 JShell -- 版本 11.0.2
| 要大致了解該版本, 請鍵入: /help intro
jshell> /help intro
|
| intro
| =====
|
| 使用 jshell 工具可以執行 Java 代碼,從而立即獲取結果。
| 您可以輸入 Java 定義(變量、方法、類等等),例如:int x = 8
| 或 Java 表達式,例如:x + x
| 或 Java 語句或導入。
| 這些小塊的 Java 代碼稱為“片段”。
|
| 這些 jshell 工具命令還可以讓您了解和
| 控制您正在執行的操作,例如:/list
|
| 有關命令的列表,請執行:/help
jshell>

Jshell確實是一個好用的小工具,這里不做過多介紹,我就舉一個例子,剩下的大家自己體會。比如我們現在就想隨機生成一個UUID,以前需要這么做:

  • 創建一個類。
  • 創建一個main方法。
  • 然后寫一個生成UUID的邏輯,執行。

現在只需要,進入打開終端鍵入jshell,然后直接輸入var uuid = UUID.randomUUID()回車。就可以看到uuid的回顯,這樣我們就得到了一個uuid。并不需要public static void main(String[] args);

 [email protected]  ~  jshell
| 歡迎使用 JShell -- 版本 11.0.2
| 要大致了解該版本, 請鍵入: /help intro
jshell> var uuid = UUID.randomUUID();
uuid ==> 9dac239e-c572-494f-b06d-84576212e012
jshell>

3.怎么退出Jshell?

在Jshell環境中鍵入/exit就可以退出。

 [email protected]  ~ 
[email protected]  ~  jshell
| 歡迎使用 JShell -- 版本 11.0.2
| 要大致了解該版本, 請鍵入: /help intro
jshell> var uuid = UUID.randomUUID();
uuid ==> 9dac239e-c572-494f-b06d-84576212e012
jshell> /exit
| 再見
[email protected]  ~ 

模塊化(Module)@since 9

1.什么是模塊化?

模塊化就是增加了更高級別的聚合,是Package的封裝體。Package是一些類路徑名字的約定,而模塊是一個或多個Package組成的封裝體。

java9以前 :package => class/interface。

java9以后 :module => package => class/interface。

那么JDK被拆為了哪些模塊呢?打開終端執行java --list-modules查看。

[email protected]  ~ java --list-modules
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
jdk.interna[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

2.為什么這么做?

大家都知道JRE中有一個超級大的rt.jar(60多M),tools.jar也有幾十兆,以前運行一個hello world也需要上百兆的環境。

  • 讓Java SE程序更加容易輕量級部署。
  • 強大的封裝能力。
  • 改進組件間的依賴管理,引入比jar粒度更大的Module。
  • 改進性能和安全性。

3.怎么定義模塊?

模塊的是通過module-info.java進行定義,編譯后打包后,就成為一個模塊的實體。下面來看下最簡單的模塊定義。

趕快看看Java11,不然你就out了

4.模塊的關鍵字

· open

用來指定開放模塊,開放模塊的所有包都是公開的,public的可以直接引用使用,其他類型可以通過反射得到。

open module module.one {
//導入日志包
requires java.logging;
}

· opens

opens 用來指定開放的包,其中public類型是可以直接訪問的,其他類型可以通過反射得到。

module module.one {
opens <package>;
}

· exports

exports用于指定模塊下的哪些包可以被其他模塊訪問。

module module.one {

exports <package>;

exports <package> to <module1>, <module2>...;
}

· requires

該關鍵字聲明當前模塊與另一個模塊的依賴關系。

module module.one {
requires <package>;
}

· uses、provides…with…

uses語句使用服務接口的名字,當前模塊就會發現它,使用java.util.ServiceLoader類進行加載,必須是本模塊中的,不能是其他模塊中的.其實現類可以由其他模塊提供。

module module.one {
//對外提供的接口服務 ,下面指定的接口以及提供服務的impl,如果有多個實現類,用用逗號隔開
uses <接口名>;
provides <接口名> with <接口實現類>,<接口實現類>;
}

var關鍵字 @since 10

1.var是什么?

var是Java10中新增的局部類型變量推斷。它會根據后面的值來推斷變量的類型,所以var必須要初始化。

例:var a; ?
var a = 1; ?

2.var使用示例

· var定義局部變量

var a = 1; 
等于
int a = 1;

· var接收方法返回時

var result = this.getResult();
等于
String result = this.getResult();

· var循環中定義局部變量

for (var i = 0; i < 5; i++) {
System.out.println(i);
}
等于
for (int i = 0; i < 5; i++) {
System.out.println(i);
}

· var結合泛型

var list1 = new ArrayList<String>(); //在<>中指定了list類型為String
等于
List<String> list1 = new ArrayList<>();
var list2 = new ArrayList<>(); //<>里默認會是Object

· var在Lambda中使用(java11才可以使用)

Consumer<String> Consumer = (var i) -> System.out.println(i);
等于
Consumer<String> Consumer = (String i) -> System.out.println(i);

3.var不能再哪里使用?

  • 類成員變量類型。
  • 方法返回值類型。
  • Java10中Lambda不能使用var,Java11中可以使用。

增強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<String>(); // 這里返回正常的集合
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<String>();
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個方法:

· ofNullable(T t)

此方法可以接收null來創建一個空流

以前
Stream.of(null); //報錯
現在
Stream.ofNullable(null);

· takeWhile(Predicate<? super T> predicate)

此方法根據Predicate接口來判斷如果為true就 取出 來生成一個新的流,只要碰到false就終止,不管后邊的元素是否符合條件。

 Stream<Integer> integerStream = Stream.of(6, 10, 11, 15, 20);
Stream<Integer> takeWhile = integerStream.takeWhile(t -> t % 2 == 0);
takeWhile.forEach(System.out::println); // 6,10

· dropWhile(Predicate<? super T> predicate)

此方法根據Predicate接口來判斷如果為true就 丟棄 來生成一個新的流,只要碰到false就終止,不管后邊的元素是否符合條件。

 Stream<Integer> integerStream = Stream.of(6, 10, 11, 15, 20);
Stream<Integer> takeWhile = integerStream.dropWhile(t -> t % 2 == 0);
takeWhile.forEach(System.out::println); //11,15,20

· iterate重載

以前使用iterate方法生成無限流需要配合limit進行截斷

 Stream<Integer> limit = Stream.iterate(1, i -> i + 1).limit(5);
limit.forEach(System.out::println); //1,2,3,4,5

現在重載后這個方法增加了個判斷參數

 Stream<Integer> iterate = Stream.iterate(1, i -> i <= 5, i -> i + 1);
iterate.forEach(System.out::println); //1,2,3,4,5

4.Optional增強 @since 9

· stream()

如果為空返回一個空流,如果不為空將Optional的值轉成一個流。

 //返回Optional值的流
Stream<String> stream = Optional.of("Java 11").stream();
stream.forEach(System.out::println); // Java 11

//返回空流
Stream<Object> stream = Optional.ofNullable(null).stream();
stream.forEach(System.out::println); //

· 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<Integer> 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.

· or(Supplier<? extends Optional<? extends T>> supplier)

 Optional<String> optional1 = Optional.of("Java");
Supplier<Optional<String>> 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<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
// 異步
CompletableFuture<HttpResponse<String>> sendAsync = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
//這里會阻塞
HttpResponse<String> response1 = sendAsync.get();
System.out.println(response1.body());

直接運行java文件

我們都知道以前要運行一個.java文件,首先要javac編譯成.class文件,然后在java執行:

//編譯
javac Java11.java
//運行
java Java11

在java11中,只需要通過java一個命令就可以搞定

java Java11.java

移除內容

  • 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約束

Java 10的這個改進在Docker for Mac、Docker for Windows以及Docker Enterprise Edition等環境均有效。

總結

趕快看看Java11,不然你就out了

我來說兩句
您需要登錄后才可以評論 登錄 | 立即注冊
facelist
所有評論(0)
領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

安卓版28杠游戏