趕快看看Java11,否則你就out了! 這個是我的博客原文的連接。Java更新的太快了,都學不過來了,最近了解一些Java8之後的一些特性,寫下來但願對你們有幫助。java
因爲直接從Java8跨越到Java11,因此特性介紹就把Java9-Java11的部分特性一塊兒介紹一下。想要了解Java8特性的朋友能夠去個人博客找「Java8系列」。git
Jshell在Java9中就被提出來了,能夠直接在終端寫Java程序,回車就能夠執行。Jshell默認會導入下面的一些包,因此在Jshell環境中這些包的內容都是可使用的。github
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.*;
複製代碼
Jshell是在 Java 9 中引入的。它提供了一個交互式 shell,用於快速原型、調試、學習 Java 及 Java API,全部這些都不須要 public static void main 方法,也不須要在執行以前編譯代碼。sql
打開終端,鍵入jshell進入jshell環境,而後輸入/help intro能夠查看Jshell的介紹。docker
lixiaoshuang@localhost ~ 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,之前須要這麼作:shell
如今只須要,進入打開終端鍵入jshell,而後直接輸入var uuid = UUID.randomUUID()
回車。就能夠看到uuid的回顯,這樣咱們就獲得了一個uuid。並不須要public static void main(String[] args);segmentfault
lixiaoshuang@localhost ~ jshell | 歡迎使用 JShell -- 版本 11.0.2 | 要大體瞭解該版本, 請鍵入: /help intro jshell> var uuid = UUID.randomUUID(); uuid ==> 9dac239e-c572-494f-b06d-84576212e012 jshell> 複製代碼
在Jshell環境中鍵入/exit
就能夠退出。api
lixiaoshuang@localhost ~ lixiaoshuang@localhost ~ jshell | 歡迎使用 JShell -- 版本 11.0.2 | 要大體瞭解該版本, 請鍵入: /help intro jshell> var uuid = UUID.randomUUID(); uuid ==> 9dac239e-c572-494f-b06d-84576212e012 jshell> /exit | 再見 lixiaoshuang@localhost ~ 複製代碼
模塊化就是增長了更高級別的聚合,是Package的封裝體。Package是一些類路徑名字的約定,而模塊是一個或多個Package組成的封裝體。安全
java9之前 :package => class/interface。bash
java9之後 :module => package => class/interface。
那麼JDK被拆爲了哪些模塊呢?打開終端執行java --list-modules
查看。
lixiaoshuang@localhost ~ java --list-modules
java.base@11.0.2
java.compiler@11.0.2
java.datatransfer@11.0.2
java.desktop@11.0.2
java.instrument@11.0.2
java.logging@11.0.2
java.management@11.0.2
java.management.rmi@11.0.2
java.naming@11.0.2
java.net.http@11.0.2
java.prefs@11.0.2
java.rmi@11.0.2
java.scripting@11.0.2
java.se@11.0.2
java.security.jgss@11.0.2
java.security.sasl@11.0.2
java.smartcardio@11.0.2
java.sql@11.0.2
java.sql.rowset@11.0.2
java.transaction.xa@11.0.2
java.xml@11.0.2
java.xml.crypto@11.0.2
jdk.accessibility@11.0.2
jdk.aot@11.0.2
jdk.attach@11.0.2
jdk.charsets@11.0.2
jdk.compiler@11.0.2
jdk.crypto.cryptoki@11.0.2
jdk.crypto.ec@11.0.2
jdk.dynalink@11.0.2
jdk.editpad@11.0.2
jdk.hotspot.agent@11.0.2
jdk.httpserver@11.0.2
jdk.internal.ed@11.0.2
jdk.internal.jvmstat@11.0.2
jdk.internal.le@11.0.2
jdk.internal.opt@11.0.2
jdk.internal.vm.ci@11.0.2
jdk.internal.vm.compiler@11.0.2
jdk.internal.vm.compiler.management@11.0.2
jdk.jartool@11.0.2
jdk.javadoc@11.0.2
jdk.jcmd@11.0.2
jdk.jconsole@11.0.2
jdk.jdeps@11.0.2
jdk.jdi@11.0.2
jdk.jdwp.agent@11.0.2
jdk.jfr@11.0.2
jdk.jlink@11.0.2
jdk.jshell@11.0.2
jdk.jsobject@11.0.2
jdk.jstatd@11.0.2
jdk.localedata@11.0.2
jdk.management@11.0.2
jdk.management.agent@11.0.2
jdk.management.jfr@11.0.2
jdk.naming.dns@11.0.2
jdk.naming.rmi@11.0.2
jdk.net@11.0.2
jdk.pack@11.0.2
jdk.rmic@11.0.2
jdk.scripting.nashorn@11.0.2
jdk.scripting.nashorn.shell@11.0.2
jdk.sctp@11.0.2
jdk.security.auth@11.0.2
jdk.security.jgss@11.0.2
jdk.unsupported@11.0.2
jdk.unsupported.desktop@11.0.2
jdk.xml.dom@11.0.2
jdk.zipfs@11.0.2
複製代碼
你們都知道JRE中有一個超級大的rt.jar(60多M),tools.jar也有幾十兆,之前運行一個hello world也須要上百兆的環境。
模塊的是經過module-info.java進行定義,編譯後打包後,就成爲一個模塊的實體。下面來看下最簡單的模塊定義。
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是Java10中新增的局部類型變量推斷。它會根據後面的值來推斷變量的類型,因此var必需要初始化。
例:
var a; ❌
var a = 1; ✅
複製代碼
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);
複製代碼
// 判斷字符串是否爲空白 " ".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 複製代碼
從Java 9 開始,jdk裏面就爲集合(List、Set、Map)增長了of和copyOf方法。它們用來建立不可變集合。
示例一:
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。
。
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
複製代碼
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 複製代碼
String lxs = "java"; try (var inputStream = new ByteArrayInputStream(lxs.getBytes()); var outputStream = new ByteArrayOutputStream()) { inputStream.transferTo(outputStream); System.out.println(outputStream); //java } 複製代碼
改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文件,首先要javac編譯成.class文件,而後在java執行:
//編譯
javac Java11.java
//運行
java Java11
複製代碼
在java11中,只須要經過java一個命令就能夠搞定
java Java11.java
複製代碼
許多運行在Java虛擬機中的應用程序(包括Apache Spark和Kafka等數據服務以及傳統的企業應用程序)均可以在Docker容器中運行。可是在Docker容器中運行Java應用程序一直存在一個問題,那就是在容器中運行JVM程序在設置內存大小和CPU使用率後,會致使應用程序的性能降低。這是由於Java應用程序沒有意識到它正在容器中運行。隨着Java 10的發佈,這個問題總算得以解決,JVM如今能夠識別由容器控制組(cgroups)設置的約束。能夠在容器中使用內存和CPU約束來直接管理Java應用程序,其中包括:
Java 10的這個改進在Docker for Mac、Docker for Windows以及Docker Enterprise Edition等環境均有效。
感謝你們的觀看,但願多多關注哦。 若有錯誤,煩請指正。