Java9新特性主要發生的改變:
模塊化系統
1,模塊將由通常的類和新的模塊聲明文件(module-info.java)組成。該文件是位於java代碼結構的頂層,該模塊描述符明確地定義了我們的模塊需要什麼依賴關係,以及哪些模塊被外部使用。在exports子句中未提及的所有包默認情況下將封裝在模塊中,不能在外部使用。例子如下:
2,要是module-info.java不能創建,請檢查jdk的版本,要求jdk9以上的版本
3,要想在Test01模塊中調用Test02模塊下包中的結構,需要在Test02的module-info.java中聲明:
module Test02 {
//exports :控制着哪些包可以被其它模塊訪問到 。 所有不被導出的包默認都被封裝在模塊裏面
exports bean;
}
4,對應在Test01 模塊的src下創建module-info.java文件:
module Test01 {
//requires :指明對其它模塊的依賴。
requires Test02;
}
Java 的REPL工具: jShell
像Python 和 Scala 之類的語言早就有交互式編程環境 REPL (read - evaluate - print -loop)了,以交互式的方式對語句和表達式進行求值。開發者只需要輸入一些代碼,就可以在編譯前獲得對程序的反饋。而之前的Java版本要想執行代碼,必須創建文件、聲明類、提供測試方法方可實現。
1,調出 jShell
jshell
2,獲取幫助
3,沒有受檢異常 ( 編譯時異常)
4,使用外部代碼編輯器來編寫Java
5,退出
接口中聲明私有方法
jdk9中允許接口中定義私有的方法
接口中的靜態方法只能由接口自己調用,接口的實現類不能調用接口的靜態方法,使用如下:
interface MyInterface {
void normalInterfaceMethod();
default void methodDefault1() {
init();
}
public default void methodDefault2() {
init();
}
// This method is not part of the public API exposed by MyInterface
private void init() {
System.out.println("默認方法中的通用操作");
}
}
class MyInterfaceImpl implements MyInterface {
@Override
public void normalInterfaceMethod() {
System.out.println("實現接口的方法");
}
}
public class MyInterfaceTest {
public static void main(String[] args) {
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.methodDefault1();
// impl.init();//不能調用
}
}
鑽石操作符使用升級
1,鑽石操作符與匿名內部類在java8中不能共存,在Java9可以
2,我們將能夠與匿名實現類共同使用鑽石操作符(diamond operator)在Java 8
中如下的操作是會報錯的,如下:
//編譯報錯信息:Cannot use “<>” with anonymous inner classes.在java9中則可以編譯通過
Comparator<Object> com = new Comparator<>(){
@Override
public int compare(Object o1, Object o2) {
return 0;
}
};
try結構的語法升級
1,Java 8 中,可以實現資源的自動關閉,但是要求執行後必須關閉的所有資源必須在try子句中初始化,否則編譯不通過。如下例所示:
try(InputStreamReader reader = new InputStreamReader(System.in)){
//讀取數據細節省略
}catch (IOException e){
e.printStackTrace();
}
2,Java 9 中,用資源語句編寫try將更容易,我們可以在try子句中使用已經初始化過的資源,此時的資源是final的:
InputStreamReader reader = new InputStreamReader(System.in);
OutputStreamWriter writer = new OutputStreamWriter(System.out);
try(reader;writer){
//reader是final的,不可再被賦值
//reader = null;
char[] chars = new char[20];
int len;
if((len = reader.read(chars)) != -1){
String str = new String(chars,0,len);
writer.write(str,0,len);
}
}catch (IOException e){
e.printStackTrace();
}
String底層存儲結構的變更
String 再也不用 char[] 來存儲啦,改成了 byte[] 加上編碼標記,節約了一些空間,StringBuffer和StringBuilder也隨着改變。
集合工廠方法創建只讀集合
1,jdk8要創建一個只讀、不可改變的集合,必須構造和分配它,然後添加元素,最後包裝成一個不可修改的集合。
List<String> namesList = new ArrayList <>();
namesList.add("Tommey");
namesList.add("Bob");
namesList.add("CC");
namesList = Collections.unmodifiableList(namesList);
System.out.println(namesList);
2,jdk9調用集合中靜態方法of(),可以將不同數量的參數傳輸到此工廠方法中。此功能可用於Set和List,也可用於Map的類似形式。此時得到的集合,是不可變的:在創建後,繼續添加元素到這些集合會導致 “UnsupportedOperationException” 。
List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("a", "b", "c");
Map<String, Integer> map1 = Map.of("Tom", 12, "Jerry", 21, "Lilei", 33, "HanMeimei", 18);
Map<String, Integer> map2 = Map.ofEntries(Map.entry("Tom", 89),Map.entry("Jim", 78), Map.entry("Tim", 98));
InputStream中transferTo()方法
InputStream 終於有了一個非常有用的方法:transferTo,可以用來將數據直接
傳輸到 OutputStream,使用如下:
ClassLoader cl = this.getClass().getClassLoader();
try (InputStream is = cl.getResourceAsStream("hello.txt");
OutputStream os = new FileOutputStream("src\\hello1.txt")) {
is.transferTo(os); // 把輸入流中的所有數據直接自動地複製到輸出流中
} catch (IOException e) {
e.printStackTrace();
}
StreamAPI新增的4個方法
Stream 接口中添加了 4 個新的方法:takeWhile, dropWhile, ofNullable,還有個 iterate 方法的新重載方法,可以讓你提供一個 Predicate (判斷條件)來指定什麼時候結束迭代
1,takeWhile() 的使用:
用於從 Stream 中獲取一部分數據,接收一個 Predicate 來進行選擇。在有序的Stream 中takeWhile 返回從開頭開始的儘量多的元素。
List<Integer> list = Arrays.asList(45, 43, 76, 87, 42, 77, 90, 73, 67, 88);
list.stream().takeWhile(x -> x < 50).forEach(System.out::println);//45,43
2,dropWhile()的使用:
dropWhile 的行爲與 takeWhile 相反,返回剩餘的元素。
list.stream().dropWhile(x -> x < 50).forEach(System.out::println);//76 ,87 ,42 ,77 ,90 ,73 ,67 ,88
3,ofNullable()的使用:
Java 8 中 Stream 不能完全爲null,否則會報空指針異常。而 Java 9 中的 ofNullable 方法允許我們創建一個單元素 Stream,可以包含一個非空元素,也可以創建一個空Stream。
// 報NullPointerException
// Stream<Object> stream1 = Stream.of(null);
// System.out.println(stream1.count());
Stream<String> stringStream = Stream.of("AA", "BB", null);
System.out.println(stringStream.count());// 3
// ofNullable():允許值爲null
Stream<Object> stream1 = Stream.ofNullable(null);
System.out.println(stream1.count());// 0
Stream<String> stream = Stream.ofNullable("hello world");
System.out.println(stream.count());// 1
4,ofNullable()的使用:
這個 iterate 方法的新重載方法,可以讓你提供一個 Predicate (判斷條件)來指定什麼時候結束迭代。
// 原來的控制終止方式:
Stream.iterate(1, i -> i + 1).limit(10).forEach(System.out::println);
// 現在的終止方式:
Stream.iterate(1, i -> i < 100, i -> i + 1).forEach(System.out::println);
Optional的新方法stream()
Optional類中stream()的使用:
List<String> list = new ArrayList<>();
list.add("Tommey");
list.add("Tom");
Optional<List<String>> optional = Optional.ofNullable(list);
Stream<List<String>> stream = optional.stream();
stream.flatMap(x -> x.stream()).forEach(System.out::println);
升級的Nashorn引擎
Nashorn 項目在 JDK 9 中得到改進,它爲 Java 提供輕量級的 Javascript 運行時。 JDK 9 包含一個用來解析 Nashorn 的 ECMAScript 語法樹的 API。這個 API 使得IDE 和服務端框架不需要依賴 Nashorn 項目的內部實現類,就能夠分析ECMAScript 代碼。