Java 8
Java 8 (又稱為 jdk 1.8) 是 Java 語言開發的一個主要版本。 Oracle 公司於 2014 年 3 月 18 日發布 Java 8 ,它支持函數式編程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。
新特性
Java8 新增了非常多的特性,我們主要討論以下幾個:
-
Lambda 表達式 − Lambda允許把函數作為一個方法的參數(函數作為參數傳遞進方法中。
-
方法引用 − 方法引用提供了非常有用的語法,可以直接引用已有Java類或對象(實例)的方法或構造器。與lambda聯合使用,方法引用可以使語言的構造更緊湊簡潔,減少冗余代碼。
-
默認方法 − 默認方法就是一個在接口里面有了一個實現的方法。
-
新工具 − 新的編譯工具,如:Nashorn引擎 jjs、 類依賴分析器jdeps。
-
Stream API −新添加的Stream API(java.util.stream) 把真正的函數式編程風格引入到Java中。
-
Date Time API − 加強對日期與時間的處理。
-
Optional 類 − Optional 類已經成為 Java 8 類庫的一部分,用來解決空指針異常。
-
Nashorn, JavaScript 引擎 − Java 8提供了一個新的Nashorn javascript引擎,它允許我們在JVM上運行特定的javascript應用。
更多的新特性可以參閱官網:What's New in JDK 8
詳細的新特性:
序號 | 特性 |
---|---|
1 | Lambda 表達式 |
2 | 方法引用 |
3 | 函數式接口 |
4 | 默認方法 |
5 | Stream |
6 | Optional 類 |
7 | Nashorn, JavaScript 引擎 |
8 | 新的日期時間 API |
9 | Base64 |
排序的示例
// 使用 java 7 排序 private void sortUsingJava7(List<String> names){ Collections.sort(names, new Comparator<String>() { @Override public int compare(String s1, String s2) { return s1.compareTo(s2); } }); } // 使用 java 8 排序 private void sortUsingJava8(List<String> names){ Collections.sort(names, (s1, s2) -> s1.compareTo(s2)); }
JAVA 9
Java 9 發布於 2017 年 9 月 22 日,帶來了很多新特性,其中最主要的變化是已經實現的模塊化系統。接下來我們會詳細介紹 Java 9 的新特性。
新特性
- 模塊系統:模塊是一個包的容器,Java 9 最大的變化之一是引入了模塊系統(Jigsaw 項目)。
- REPL (JShell):交互式編程環境。
- HTTP 2 客戶端:HTTP/2標准是HTTP協議的最新版本,新的 HTTPClient API 支持 WebSocket 和 HTTP2 流以及服務器推送特性。
- 改進的 Javadoc:Javadoc 現在支持在 API 文檔中的進行搜索。另外,Javadoc 的輸出現在符合兼容 HTML5 標准。
- 多版本兼容 JAR 包:多版本兼容 JAR 功能能讓你創建僅在特定版本的 Java 環境中運行庫程序時選擇使用的 class 版本。
- 集合工廠方法:List,Set 和 Map 接口中,新的靜態工廠方法可以創建這些集合的不可變實例。
- 私有接口方法:在接口中使用private私有方法。我們可以使用 private 訪問修飾符在接口中編寫私有方法。
- 進程 API: 改進的 API 來控制和管理操作系統進程。引進 java.lang.ProcessHandle 及其嵌套接口 Info 來讓開發者逃離時常因為要獲取一個本地進程的 PID 而不得不使用本地代碼的窘境。
- 改進的 Stream API:改進的 Stream API 添加了一些便利的方法,使流處理更容易,並使用收集器編寫復雜的查詢。
- 改進 try-with-resources:如果你已經有一個資源是 final 或等效於 final 變量,您可以在 try-with-resources 語句中使用該變量,而無需在 try-with-resources 語句中聲明一個新變量。
- 改進的棄用注解 @Deprecated:注解 @Deprecated 可以標記 Java API 狀態,可以表示被標記的 API 將會被移除,或者已經破壞。
- 改進鑽石操作符(Diamond Operator) :匿名類可以使用鑽石操作符(Diamond Operator)。
- 改進 Optional 類:java.util.Optional 添加了很多新的有用方法,Optional 可以直接轉為 stream。
- 多分辨率圖像 API:定義多分辨率圖像API,開發者可以很容易的操作和展示不同分辨率的圖像了。
- 改進的 CompletableFuture API : CompletableFuture 類的異步機制可以在 ProcessHandle.onExit 方法退出時執行操作。
- 輕量級的 JSON API:內置了一個輕量級的JSON API
- 響應式流(Reactive Streams) API: Java 9中引入了新的響應式流 API 來支持 Java 9 中的響應式編程。
更多的新特性可以參閱官網:What's New in JDK 9
詳細的:
序號 | 特性 |
---|---|
1 | 模塊系統 |
2 | REPL (JShell) |
3 | 改進的 Javadoc |
4 | 多版本兼容 JAR 包 |
5 | 集合工廠方法 |
6 | 私有接口方法 |
7 | 進程 API |
8 | Stream API |
9 | try-with-resources |
10 | @Deprecated |
11 | 內部類的鑽石操作符(Diamond Operator) |
12 | Optional 類 |
13 | 多分辨率圖像 API |
14 | CompletableFuture API |
Java 11
美國時間 2018年09 月 25 日,Oralce 正式發布了 Java 11,這是據 Java 8 以后支持的首個長期版本。
Java 8 擴展支持到 2025 年,而 Java 11 擴展支持到 2026 年。Java 11 長期支持,也已經包含了 9 和 10 的全部功能,9 和 10 自然就活到頭了。
局部變量類型推斷
var str = "我是劉zzz"; var list = new ArrayList<>(); list.add("aa"); list.add("bb"); list.add("cc"); list.add(233);//如果 new ArrayList<Strnig>規定的泛型是 String,就不能這么寫了 list.forEach(s-> System.out.println(s));
lamada 語法
new Thread(()->{ for (int i=0; i<5; i++){ System.out.println(i); } }).start(); public interface Customer { void accpet(String str); } Customer customer = (var str1) -> System.out.println(str1.toUpperCase()); customer.accpet("sdflksjf");
增強的方法
//集合的創建可以更簡單,Set 也有 of() List<String> list1 = List.of("aa","bb","cc");//Arrays.asList() 效果一樣 list1.add("dd");//java.lang.UnsupportedOperationException System.out.println(list1);
Stream 流
/** * 流的處理的三個步驟 * 1,創建流 * 2,中間操作 * 3,終止操作 */ Stream<Integer> stream1 = Stream.of(1,10, 3, 20, 30, 50); //stream.forEach(t-> System.out.println(t)); stream1.forEach(System.out::println);//有參數無返回值 //如果為空不會報錯,但傳入null會報空指針, Stream<Object> stream2 = Stream.of();//Stream.of(null); stream2.forEach(System.out::println); //對於 null 的情況,可以用 ofNullable Stream<Object> stream3 = Stream.ofNullable(null); stream3.forEach(System.out::println); System.out.println("****************"); Stream<Integer> stream4 = Stream.of(1,5, 3, 20, 30, 50); //Stream<Integer> takeWhile = stream4.takeWhile(t -> t % 2 != 0);//為奇數時留下,形成新 Stream //takeWhile.forEach(System.out::println); Stream<Integer> dropWhile = stream4.dropWhile(t -> t % 2 != 0);//為奇數時丟棄,形成新 Stream dropWhile.forEach(System.out::println); //流的迭代,創建流 Stream<Integer> iterate = Stream.iterate(1, t -> (2 * t) + 1); //如果不加limit(10),會無限迭代輸出,這是 jdk11 之前的做法(用 limit 限制) iterate.limit(10).forEach(System.out::println); //jdk 11 的做法 System.out.println("***************"); Stream<Integer> stream = Stream.iterate(1, t -> t < 1000, t -> (2 * t) + 1); stream.forEach(System.out::println);
字符串和 Operational
String str1 = "\t \n\r "; //判斷字符串是否是空白字符 System.out.println(str1.isBlank()); System.out.println("*****==========="); str1 = "\t abc \r \n "; //去除字符串首尾中的空白,包括英文和其它所有語言的空白字符 String strip = str1.strip(); //去除字符串首部的空白,包括漢字 String stripLeading = strip.stripLeading(); //去除字符串尾部的空白,包括漢字 String stripTrailing = strip.stripTrailing(); System.out.println(strip+"<====>"+strip.length()); str1 = "java"; str1.repeat(3);//把str1 重復三次,輸出 javajavajava //去除字符串首尾中的空白,只能去除碼值小於32的(如果是中文全角的空白是去除不了的) String trim = str1.trim(); System.out.println(trim+"<====>"+trim.length());
String str = null; //of 和 get() 都不建議用,如果傳入的null,會報空指針 /**Optional<String> stringOptional = Optional.of(str); System.out.println(stringOptional.get());**/ //一般用 ofNullable,取值用 orElse() Optional<String> optionalS = Optional.ofNullable(str); //如果str不為null,返回str的內容,否則返回 "空串代替" String orElse = optionalS.orElse("空串代替"); ////如果 str 不為null,返回 str 的內容,否則執行 f() 方法 orElse = optionalS.orElse(f()); System.out.println(orElse); //orElse 和 orElseGet 區別:無論 str是否為空,orElse里面的都會執行,orElseGet 只有 str 為空才執行 String orElseGet = optionalS.orElseGet(() -> f()); System.out.println(orElseGet); //orElseThrow也有重載方法,跟orElseGet 用法類似.. String orElseThrow = optionalS.orElseThrow(); System.out.println(orElseThrow);//拋出 NoSuchElementException,底層還是空指針,不過源碼做了控制而已
static String f(){ System.out.println("執行了f() 這個方法"); return "lhg"; }
字符串和輸入流的 API
以前輸入輸出文件
FileInputStream fis = new FileInputStream("D:\\ideaProjects\\Demo_JDK12\\src\\com\\lhg\\demo\\StringTest.java"); FileOutputStream fos = new FileOutputStream("d://demo.java"); BufferedReader br = new BufferedReader(new FileReader("D:\\ideaProjects\\Demo_JDK12\\src\\com\\lhg\\demo\\StringTest.java")); BufferedWriter bw = new BufferedWriter(new FileWriter("d:/demo3.java")); byte[] buff = new byte[fis.available()];//fis.available():得到文件的有效字節數 int len;//讀進緩沖數組里面 String line; //br bw方式 while ((line = br.readLine()) != null){ bw.write(line); bw.newLine(); } //fis fos 方式 while((len=fis.read(buff)) != -1){ fos.write(buff, 0, len); } fos.close(); fis.close(); bw.close(); br.close();
通過 Stream
FileInputStream fis = new FileInputStream("D:\\ideaProjects\\Demo_JDK12\\src\\com\\lhg\\demo\\StringTest.java"); byte[] buff = new byte[fis.available()];//fis.available():得到文件的有效字節數 int len;//讀進緩沖數組里面 fis.close(); String string = new String(buff); string.lines().forEach(System.out::println);//可以直接輸出或其它操作
transfer 復制流
InputStream is = StringTest.class.getClassLoader().getResourceAsStream("config.properties"); try(var os = new FileOutputStream("config_bak.properties")){ is.transferTo(os);//輸入流的數據自動復制到輸出流 } is.close();
Http 客戶端
更簡化的編譯運行程序
之前的做法是 先javac Demo.java,然后java Demo 運行程序,
現在直接 java Demo.java 一步到位,不過 Demo.java 文件中所引用的 類必須全部來自文件本身(比如這個類 引用了 Teacher 這個類,那么 Teacher 這個類必須定義在 Demo.java 中),如果 Demo.java 中有多個類,多個 main方法,哪個類在前,就執行哪個類的 main 方法(當然只有一個 public 類)
垃圾收集器改進
默認的 gc
epsilon gc
設置好后,重新運行上面那段代碼,發現程序會因為堆空間不足很快退出
ZGC java 11 最為矚目的特性沒有之一
參考
Java 11 正式發布,這 8 個逆天新特性教你寫出更牛逼的代碼