jdk1.5-1.10新特性

VirtiL發表於2019-01-22

從網上搜集摘錄的jdk特性,在這裡記錄下來以便自我學習.

jdk5新特性
    1、自動裝箱和拆箱
    2、列舉
    3、靜態匯入
    4、可變引數
    5、內省
       是Java語言對Bean類屬性、事件的一種預設處理方法。例如類A中有屬性那麼,那我們可以通過getName,setName來得到其值或者設定新的值。通過getName/setName來訪問name屬性,這就是預設的規則。Java中提供了一套API用來訪問某個屬性的getter,setter方法,通過這些API可以使你不需要了解這個規則,這些API存放於包java.beans中。
       一般的做法是通過類Introspector來獲取某個物件的BeanInfo資訊,然後通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的getter/setter方法,然後我們就可以通過反射機制來呼叫這些方法。
    6、泛型
    7、For-Each迴圈

jdk6新特性
    1、Desktop類和SystemTray類
       AWT新增加了兩個雷:Desktop,SystemTray。
       Desktop可以用來開啟系統預設瀏覽器指定的URL,開啟系統預設郵件客戶端給指定的郵件賬號發郵件,用預設應用程式開啟或編輯檔案(比如,用記事本開啟txt檔案),用系統預設的印表機列印文件
       SystemTray可以用來在系統托盤區建立一個托盤程式
    2、使用JAXB2來實現物件與XML之間的對映
       也就是物件與XML之間的對映(OXM),也可以通過XMLBeans和Castor等來實現同樣的功能。
    3、StAX
       StAX是The Streaming API for XML的縮寫,一種利用拉模式解析(pull-parsing)XML文件的API.StAX通過提供一種基於事件迭代器(Iterator)的API讓 程式設計師去控制xml文件解析過程,程式遍歷這個事件迭代器去處理每一個解析事件,解析事件可以看做是程式拉出來的,也就是程式促使解析器產生一個解析事件 然後處理該事件,之後又促使解析器產生下一個解析事件,如此迴圈直到碰到文件結束符; 
                SAX也是基於事件處理xml文件,但卻 是用推模式解析,解析器解析完整個xml文件後,才產生解析事件,然後推給程式去處理這些事件;DOM 採用的方式是將整個xml文件對映到一顆記憶體樹,這樣就可以很容易地得到父節點和子結點以及兄弟節點的資料,但如果文件很大,將會嚴重影響效能。
    4、使用Compiler API
                使用JDK6的Compiler API去動態的編譯Java原始檔,Compiler API結合反射功能就可以實現動態的產生Java程式碼並編譯執行這些程式碼。
    5、輕量級Http Server API
    6、插入式註解處理API
    7、用Console開發控制檯程式
    8、對指令碼語言的支援如:ruby,groovy,javascript
    9、Common Annotations

jdk7新特性
    1、switch中可以使用字串
    2、泛型的自動判斷
    3、自定義自動關閉類(實現AutoCloseable介面)
    4、新增一些取環境資訊的工具方法(System中的方法)
    5、Boolean型別反轉,空指標安全,引數與位運算
    6、兩個char間的equals
    7、安全的加減乘除

    1、對Java集合(Collections)的增強支援
       List<String> list=[“item”]; //向List集合中新增元素
       String item=list[0]; //從List集合中獲取元素
       Set<String> set={“item”}; //向Set集合物件中新增元
       Map<String,Integer> map={“key”:1}; //向Map集合中新增物件
       int value=map[“key”]; //從Map集合中獲取物件
       但是經過自己測試,按照上面的使用方法,並不能建立集合。
    2、int支援二進位制資料
    3、在try catch異常捕捉中,一個catch可以寫多個異常型別
    Connection conn = null;
    try {
        Class.forName(“com.mysql.jdbc.Driver”);
        conn = DriverManager.getConnection(“”,””,””);
    } catch(ClassNotFoundException|SQLException ex) {
        ex.printStackTrace();
    }
    4、try catch中資源定義好之後try catch自動關閉
    try (BufferedReader in  = new BufferedReader(new FileReader(“in.txt”));
         BufferedWriter out = new BufferedWriter(new FileWriter(“out.txt”))) {
    int charRead;
    while ((charRead = in.read()) != -1) {
            System.out.printf(“%c “, (char)charRead);
            out.write(charRead);
        }
    } catch (IOException ex) {
        ex.printStackTrace();
    }
jdk8新特性
    1、介面的預設方法
    Java 8允許我們給介面新增一個非抽象的方法實現,只需要使用default關鍵字即可,這個特徵又叫做擴充套件方法,示例如下:
    public interface Formula {
        double calculate(int a);
        default double sqrt(int a) {
    return Math.sqrt(a);
        }
    }
    Formula介面在擁有calculate方法之外同時還定義了sqrt方法,實現了Formula介面的子類只需要實現一個calculate方法,預設方法sqrt將在子類上可以直接使用。
        Formula formula = new Formula() {
    @Override
    public double calculate(int a) {
    return sqrt(a * 100);
            }
        };
        System.out.println(formula.calculate(100));  // 100.0
        System.out.println(formula.sqrt(16));  // 4.0
    文中的formula被實現為一個匿名類的例項,該程式碼非常
    2、Lambda表示式
    List<String> names = Arrays.asList(“tom”,”jace”,”mike”);
    Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
    return o2.compareTo(o1);
        }
    });
    只需要給靜態方法Collections.sort傳入一個List物件以及一個比較器來指定順序排列。通常做法都是建立一個匿名的比較器物件,然後將其傳遞給sort方法。
    在Java 8中提供了更簡潔的語法,lambda表示式:
    Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
    });
    還可以更簡潔:
    Collections.sort(names, (String a, String b) -> b.compareTo(a));
    去掉大括號以及return關鍵字
    Collections.sort(names, (a,b) -> b.compareTo(a));
    Java編譯器可以自動推匯出引數型別,所以可以不用再寫一次型別。
    3、函式式介面
    Lambda表示式是如何在java的型別系統中表示的呢?
    每一個lambda表示式都對應著一個型別,通常是介面型別。而“函式式介面”是指僅僅只包含一個抽象方法的介面,每一個該型別的lambda表示式都會被匹配到這個抽象方法。因為預設方法不算抽象方法,所以也可以給自己的函式式介面新增預設方法。
    我們可以將lambda表示式當做一個抽象方法的介面型別,確保自己的介面一定達到這個要求,你只需要給你的介面新增@FunctionalInterface註解,編譯器如果發現標註了這個註解的介面有多於一個抽象方法的時候就會報錯。也就是說@ FunctionalInterface註解標註的介面只能有一個抽象方法。
    例如:
    @FunctionalInterface
    public interface Converter<F, T> {
    T convert(F from);
    }
    Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
    Integer converted = converter.convert(“123”);
    System.out.println(converted);
    以上程式碼不需要@FunctionalInterface註解也是正確的。
    4、方法與建構函式引用
    上面的程式碼也可以通過靜態方法引用來表示:
    Converter<String, Integer> converter = Integer::valueOf;
    Integer converted = converter.convert(“123”);
    System.out.println(converted);
    Java8允許使用::關鍵字來傳遞方法或者建構函式引用,上面的程式碼展示瞭如何引用一個靜態方法,我們也可以引用一個物件的方法:
    public class Person {
        String firstName;
        String lastName;
        Person() {
        }
    public Person(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
        }
    }
    指定一個用來建立Person物件的物件工廠介面:
    public interface PersonFactory<P extends Person> {
    P create(String fisrtName, String lastName);
    }
    建立Person物件
    PersonFactory<Person> personFactory = Person::new;
    Person person = personFactory.create(“Peter”,”Parker”);
    我們只需要使用Person::new 來獲取Person類建構函式的引用,Java編譯器就會自動根據PersonFactory.create方法的簽名來選擇合適的建構函式。
    5、Lambda作用域
    在lambda表示式中訪問外層作用域和老版本的匿名物件中的方式很相似。你可以直接訪問標記了final的外層區域性變數,或者例項的欄位以及靜態變數。
    6、訪問區域性變數
    我們可以直接在lambda表示式中訪問外層的區域性變數
    final int num = 1;
    Converter<Integer, String> stringConverter = (from) -> String.valueOf(from + num);
    stringConverter.convert(2);
    但是和匿名物件不同的是,這裡的變數num可以不用宣告為final,該程式碼同樣正確。
    7、訪問物件欄位與靜態變數
    和本地不良不同的是,lambda內部對於例項的欄位以及靜態變數是即可讀又可寫。該行為和匿名物件是一致的:
    static int outerStaticNum;
    int outerNum;
    public void testScopes() {
        Converter stringConverter1 = (from) -> {
            outerNum = 23;
            return String.valueOf(from);
        };
        Converter stringConverter2 = (from) -> {
            outerStaticNum = 72;
            return String.valueOf(from);
        };
    }
    8、訪問介面的預設方法
    9、Date API
    10、Annotation註解
    11.HashMap
    HashMap中的紅黑樹:HashMap中鏈長度大於8時採取紅黑樹的結構儲存。紅黑樹,除了新增的情況外,其他時候效率高於連結串列結構。
    ConcurrentHashMap:底層採用node陣列+連結串列+紅黑樹的儲存結構,通過CAS演算法(樂觀鎖機制)+synchronized來保證併發安全的實現。
    put()方法過程:
    1) 根據key的hash值陣列中相應位置的Node還未初始化,則通過CAS插入相應的資料;
    2) 如果相應位置的Node不為空,且當前該節點不處於移動狀態,則對該節點加synchronized鎖,如果該節點的hash不小於0,則遍歷連結串列更新節點或插入新節點;
    3) 如果該節點是TreeBin型別的節點,說明是紅黑樹結構,則通過putTreeVal方法往紅黑樹中插入節點;
    
jdk1.9新特性
    1. Java 平臺級模組系統
    Java 9 的定義功能是一套全新的模組系統。當程式碼庫越來越大,建立複雜,盤根錯節的“義大利麵條式程式碼”的機率呈指數級的增長。這時候就得面對兩個基礎的問題: 很難真正地對程式碼進行封裝, 而系統並沒有對不同部分(也就是 JAR 檔案)之間的依賴關係有個明確的概念。每一個公共類都可以被類路徑之下任何其它的公共類所訪問到, 這樣就會導致無意中使用了並不想被公開訪問的 API。此外,類路徑本身也存在問題: 你怎麼知曉所有需要的 JAR 都已經有了, 或者是不是會有重複的項呢? 模組系統把這倆個問題都給解決了。

    模組化的 JAR 檔案都包含一個額外的模組描述器。在這個模組描述器中, 對其它模組的依賴是通過 “requires” 來表示的。另外, “exports” 語句控制著哪些包是可以被其它模組訪問到的。所有不被匯出的包預設都封裝在模組的裡面。如下是一個模組描述器的示例,存在於 “module-info.java” 檔案中:

    module blog {
      exports com.pluralsight.blog;
     
      requires cms;
    }
    我們可以如下展示模組:

    請注意,兩個模組都包含封裝的包,因為它們沒有被匯出(使用橙色盾牌視覺化)。 沒有人會偶然地使用來自這些包中的類。Java 平臺本身也使用自己的模組系統進行了模組化。通過封裝 JDK 的內部類,平臺更安全,持續改進也更容易。

    當啟動一個模組化應用時, JVM 會驗證是否所有的模組都能使用,這基於 `requires` 語句——比脆弱的類路徑邁進了一大步。模組允許你更好地強制結構化封裝你的應用並明確依賴。你可以在這個課程中學習更多關於 Java 9 中模組工作的資訊 。

    2. Linking
    當你使用具有顯式依賴關係的模組和模組化的 JDK 時,新的可能性出現了。你的應用程式模組現在將宣告其對其他應用程式模組的依賴以及對其所使用的 JDK 模組的依賴。為什麼不使用這些資訊建立一個最小的執行時環境,其中只包含執行應用程式所需的那些模組呢? 這可以通過 Java 9 中的新的 jlink 工具實現。你可以建立針對應用程式進行優化的最小執行時映像而不需要使用完全載入 JDK 安裝版本。

    3. JShell : 互動式 Java REPL
    許多語言已經具有互動式程式設計環境,Java 現在加入了這個俱樂部。您可以從控制檯啟動 jshell ,並直接啟動輸入和執行 Java 程式碼。 jshell 的即時反饋使它成為探索 API 和嘗試語言特性的好工具。

    測試一個 Java 正規表示式是一個很好的說明 jshell 如何使您的生活更輕鬆的例子。 互動式 shell 還可以提供良好的教學環境以及提高生產力,您可以在此瞭解更多資訊。在教人們如何編寫 Java 的過程中,不再需要解釋 “public static void main(String [] args)” 這句廢話。

    4. 改進的 Javadoc
    有時一些小事情可以帶來很大的不同。你是否就像我一樣在一直使用 Google 來查詢正確的 Javadoc 頁面呢? 這不再需要了。Javadoc 現在支援在 API 文件中的進行搜尋。另外,Javadoc 的輸出現在符合相容 HTML5 標準。此外,你會注意到,每個 Javadoc 頁面都包含有關 JDK 模組類或介面來源的資訊。

    5. 集合工廠方法
    通常,您希望在程式碼中建立一個集合(例如,List 或 Set ),並直接用一些元素填充它。 例項化集合,幾個 “add” 呼叫,使得程式碼重複。 Java 9,新增了幾種集合工廠方法:

    Set<Integer> ints = Set.of(1, 2, 3);
    List<String> strings = List.of(“first”, “second”);
    除了更短和更好閱讀之外,這些方法也可以避免您選擇特定的集合實現。 事實上,從工廠方法返回已放入數個元素的集合實現是高度優化的。這是可能的,因為它們是不可變的:在建立後,繼續新增元素到這些集合會導致 “UnsupportedOperationException” 。

    6. 改進的 Stream API
    長期以來,Stream API 都是 Java 標準庫最好的改進之一。通過這套 API 可以在集合上建立用於轉換的申明管道。在 Java 9 中它會變得更好。Stream 介面中新增了 4 個新的方法:dropWhile, takeWhile, ofNullable。還有個 iterate 方法的新過載方法,可以讓你提供一個 Predicate (判斷條件)來指定什麼時候結束迭代:

    IntStream.iterate(1, i -> i < 100, i -> i + 1).forEach(System.out::println);
    第二個引數是一個 Lambda,它會在當前 IntStream 中的元素到達 100 的時候返回 true。因此這個簡單的示例是向控制檯列印 1 到 99。

    除了對 Stream 本身的擴充套件,Optional 和 Stream 之間的結合也得到了改進。現在可以通過 Optional 的新方法 `stram` 將一個 Optional 物件轉換為一個(可能是空的) Stream 物件:

    Stream<Integer> s = Optional.of(1).stream();
    在組合複雜的 Stream 管道時,將 Optional 轉換為 Stream 非常有用。

    7. 私有介面方法
    Java 8 為我們帶來了介面的預設方法。 介面現在也可以包含行為,而不僅僅是方法簽名。 但是,如果在介面上有幾個預設方法,程式碼幾乎相同,會發生什麼情況? 通常,您將重構這些方法,呼叫一個可複用的私有方法。 但預設方法不能是私有的。 將複用程式碼建立為一個預設方法不是一個解決方案,因為該輔助方法會成為公共API的一部分。 使用 Java 9,您可以向介面新增私有輔助方法來解決此問題:

    public interface MyInterface {
     
        void normalInterfaceMethod();
     
        default void interfaceMethodWithDefault() {  init(); }
     
        default void anotherDefaultMethod() { init(); }
     
        // This method is not part of the public API exposed by MyInterface
        private void init() { System.out.println(“Initializing”); }
    }
    如果您使用預設方法開發 API ,那麼私有介面方法可能有助於構建其實現。

    8. HTTP/2
    Java 9 中有新的方式來處理 HTTP 呼叫。這個遲到的特性用於代替老舊的 `HttpURLConnection` API,並提供對 WebSocket 和 HTTP/2 的支援。注意:新的 HttpClient API 在 Java 9 中以所謂的孵化器模組交付。也就是說,這套 API 不能保證 100% 完成。不過你可以在 Java 9 中開始使用這套 API:

    HttpClient client = HttpClient.newHttpClient();
     
    HttpRequest req =
       HttpRequest.newBuilder(URI.create(“http://www.google.com”))
                  .header(“User-Agent”,”Java”)
                  .GET()
                  .build();
     
     
    HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString());
    HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString());
    除了這個簡單的請求/響應模型之外,HttpClient 還提供了新的 API 來處理 HTTP/2 的特性,比如流和服務端推送。

    9. 多版本相容 JAR
    我們最後要來著重介紹的這個特性對於庫的維護者而言是個特別好的訊息。當一個新版本的 Java 出現的時候,你的庫使用者要花費數年時間才會切換到這個新的版本。這就意味著庫得去向後相容你想要支援的最老的 Java 版本 (許多情況下就是 Java 6 或者 7)。這實際上意味著未來的很長一段時間,你都不能在庫中運用 Java 9 所提供的新特性。幸運的是,多版本相容 JAR 功能能讓你建立僅在特定版本的 Java 環境中執行庫程式時選擇使用的 class 版本:

    multirelease.jar
    ├── META-INF
    │   └── versions
    │       └── 9
    │           └── multirelease
    │               └── Helper.class
    ├── multirelease
        ├── Helper.class
        └── Main.class
    在上述場景中, multirelease.jar 可以在 Java 9 中使用, 不過 Helper 這個類使用的不是頂層的 multirelease.Helper 這個 class, 而是處在“META-INF/versions/9”下面的這個。這是特別為 Java 9 準備的 class 版本,可以運用 Java 9 所提供的特性和庫。同時,在早期的 Java 諸版本中使用這個 JAR 也是能執行的,因為較老版本的 Java 只會看到頂層的這個 Helper 類。

jdk1.10新特性
    1.區域性變數型別推斷:區域性變數型別推斷將引入”var”關鍵字,也就是你可以隨意定義變數而不必指定變數的型別.
    原本需要這樣:  
    List <String> list = new ArrayList <String>(); 
    Stream <String> stream = getStream();
     
    現在你可以這樣:
     
    var list = new ArrayList <String>(); 
    var stream = getStream();
     
    說到型別推斷,從JDK 5引進泛型,到JDK 7的”<>”操作符允許不繫結型別而初始化List,再到JDK 8的Lambda表示式,再到現在JDK 10的區域性變數型別推斷,Java型別推斷正大刀闊斧的向前發展。
    2.GC改進和記憶體管理

    JDK 10中有2個JEP專門用於改進當前的垃圾收集元素。
     
    第一個垃圾收集器介面是(JEP 304),它將引入一個純淨的垃圾收集器介面,以幫助改進不同垃圾收集器的原始碼隔離。
     
    預定用於Java 10的第二個JEP是針對G1的並行完全GC(JEP 307),其重點在於通過完全GC並行來改善G1最壞情況的等待時間。G1是Java 9中的預設GC,並且此JEP的目標是使G1平行。
    3.執行緒本地握手(JEP 312)

    JDK 10將引入一種線上程上執行回撥的新方法,因此這將會很方便能停止單個執行緒而不是停止全部執行緒或者一個都不停。
    4.備用記憶體裝置上的堆分配(JEP 316)

    允許HotSpot VM在備用記憶體裝置上分配Java物件堆記憶體,該記憶體裝置將由使用者指定。
    5.其他Unicode語言 – 標記擴充套件(JEP 314)

    目標是增強java.util.Locale及其相關的API,以便實現語言標記語法的其他Unicode擴充套件(BCP 47)。
    6.基於Java的實驗性JIT編譯器

    Oracle希望將其Java JIT編譯器Graal用作Linux / x64平臺上的實驗性JIT編譯器。
    7.根證照(JEP 319)

    這個的目標是在Oracle的Java SE中開源根證照。
    8.根證照頒發認證(CA)

    這將使OpenJDK對開發人員更具吸引力,它還旨在減少OpenJDK和Oracle JDK構建之間的差異。
    9.將JDK生態整合單個儲存庫(JEP 296)

    此JEP的主要目標是執行一些記憶體管理,並將JDK生態的眾多儲存庫組合到一個儲存庫中。
    10.刪除工具javah(JEP 313)

    從JDK中移除了javah工具,這個很簡單並且很重要。