1. 程式人生 > >jdk1.7 1.8新特性

jdk1.7 1.8新特性

轉自:http://www.2cto.com/kf/201307/225968.html

本文是我學習瞭解了jdk7和jdk8的一些新特性的一些資料,有興趣的大家可以瀏覽下下面的內容。

官方文件:http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html
 
在jdk7的新特性方面主要有下面幾方面的增強:
 
1.jdk7語法上
 
   1.1二進位制變數的表示,支援將整數型別用二進位制來表示,用0b開頭。
 
   // 所有整數 int, short,long,byte都可以用二進位制表示
    // An 8-bit 'byte' value:
    byte aByte = (byte) 0b00100001;
 
    // A 16-bit 'short' value:
    short aShort = (short) 0b1010000101000101;
 
    // Some 32-bit 'int' values:
    intanInt1 = 0b10100001010001011010000101000101;
    intanInt2 = 0b101;
    intanInt3 = 0B101; // The B can be upper or lower case.
 
    // A 64-bit 'long' value. Note the "L" suffix:
    long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
 
    // 二進位制在陣列等的使用
    final int[] phases = { 0b00110001, 0b01100010, 0b11000100, 0b10001001,
    0b00010011, 0b00100110, 0b01001100, 0b10011000 };
 
1.2  Switch語句支援string型別
 
       public static String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {
         String typeOfDay;
         switch (dayOfWeekArg) {
             case "Monday":
                 typeOfDay = "Start of work week";
                 break;
             case "Tuesday":
             case "Wednesday":
             case "Thursday":
                 typeOfDay = "Midweek";
                 break;
             case "Friday":
                 typeOfDay = "End of work week";
                 break;
             case "Saturday":
             case "Sunday":
                 typeOfDay = "Weekend";
                 break;
             default:
                 throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
         }
         return typeOfDay;
    }
 
1.3 Try-with-resource語句
   
  注意:實現java.lang.AutoCloseable介面的資源都可以放到try中,跟final裡面的關閉資源類似; 按照宣告逆序關閉資源 ;Try塊丟擲的異常通過Throwable.getSuppressed獲取
 
    try (java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
    java.io.BufferedWriter writer = java.nio.file.Files
    .newBufferedWriter(outputFilePath, charset)) {
    // Enumerate each entry
    for (java.util.Enumeration entries = zf.entries(); entries
    .hasMoreElements();) {
    // Get the entry name and write it to the output file
    String newLine = System.getProperty("line.separator");
    String zipEntryName = ((java.util.zip.ZipEntry) entries
    .nextElement()).getName() + newLine;
    writer.write(zipEntryName, 0, zipEntryName.length());
    }
    }
 
1.4 Catch多個異常 說明:Catch異常型別為final; 生成Bytecode 會比多個catch小; Rethrow時保持異常型別
 
    public static void main(String[] args) throws Exception {
    try {
    testthrows();
    } catch (IOException | SQLException ex) {
    throw ex;
    }
    }
    public static void testthrows() throws IOException, SQLException {
    }
 
1.5 數字型別的下劃線表示 更友好的表示方式,不過要注意下劃線新增的一些標準,可以參考下面的示例
 
    long creditCardNumber = 1234_5678_9012_3456L;
    long socialSecurityNumber = 999_99_9999L;
    float pi = 3.14_15F;
    long hexBytes = 0xFF_EC_DE_5E;
    long hexWords = 0xCAFE_BABE;
    long maxLong = 0x7fff_ffff_ffff_ffffL;
    byte nybbles = 0b0010_0101;
    long bytes = 0b11010010_01101001_10010100_10010010;
    //float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point
    //float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point
    //long socialSecurityNumber1= 999_99_9999_L;         // Invalid; cannot put underscores prior to an L suffix
    //int x1 = _52;              // This is an identifier, not a numeric literal
    int x2 = 5_2;              // OK (decimal literal)
    //int x3 = 52_;              // Invalid; cannot put underscores at the end of a literal
    int x4 = 5_______2;        // OK (decimal literal)
    //int x5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix
    //int x6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number
    int x7 = 0x5_2;            // OK (hexadecimal literal)
    //int x8 = 0x52_;            // Invalid; cannot put underscores at the end of a number
    int x9 = 0_52;             // OK (octal literal)
    int x10 = 05_2;            // OK (octal literal)
    //int x11 = 052_;            // Invalid; cannot put underscores at the end of a number
    1.6 泛型例項的建立可以通過型別推斷來簡化 可以去掉後面new部分的泛型型別,只用<>就可以了。
      //使用泛型前
    List strList = new ArrayList();
    List<String> strList4 = new ArrayList<String>();
    List<Map<String, List<String>>> strList5 =  new ArrayList<Map<String, List<String>>>();
 
      
    //編譯器使用尖括號 (<>) 推斷型別
    List<String> strList0 = new ArrayList<String>();
    List<Map<String, List<String>>> strList1 =  new ArrayList<Map<String, List<String>>>();
    List<String> strList2 = new ArrayList<>();
    List<Map<String, List<String>>> strList3 = new ArrayList<>();
    List<String> list = new ArrayList<>();
    list.add("A");
      // The following statement should fail since addAll expects
      // Collection<? extends String>
    //list.addAll(new ArrayList<>());
 
1.7在可變引數方法中傳遞非具體化引數,改進編譯警告和錯誤
 
Heap pollution 指一個變數被指向另外一個不是相同型別的變數。例如
 
    List l = new ArrayList<Number>();
    List<String> ls = l;       // unchecked warning
    l.add(0, new Integer(42)); // another unchecked warning
    String s = ls.get(0);      // ClassCastException is thrown
    Jdk7:
    public static <T> void addToList (List<T> listArg, T... elements) {
    for (T x : elements) {
    listArg.add(x);
    }
    }
    你會得到一個warning
    warning: [varargs] Possible heap pollution from parameterized vararg type
    要消除警告,可以有三種方式
    1.加 annotation @SafeVarargs
    2.加 annotation @SuppressWarnings({"unchecked", "varargs"})
    3.使用編譯器引數 –Xlint:varargs;
 
  1.8 資訊更豐富的回溯追蹤 就是上面try中try語句和裡面的語句同時丟擲異常時,異常棧的資訊
 
    java.io.IOException  
    §?      at Suppress.write(Suppress.java:19)  
    §?      at Suppress.main(Suppress.java:8)  
    §?      Suppressed:  java.io.IOException
    §?          at Suppress.close(Suppress.java:24)
    §?          at Suppress.main(Suppress.java:9)  
    §?      Suppressed:  java.io.IOException
    §?          at  Suppress.close(Suppress.java:24)  
    §?          at  Suppress.main(Suppress.java:9)
      
 
2. NIO2的一些新特性
     
    1.java.nio.file 和java.nio.file.attribute包 支援更詳細屬性,比如許可權,所有者
    2.  symbolic and hard links支援
    3. Path訪問檔案系統,Files支援各種檔案操作
    4.高效的訪問metadata資訊
    5.遞迴查詢檔案樹,檔案擴充套件搜尋
    6.檔案系統修改通知機制
    7.File類操作API相容
    8.檔案隨機訪問增強 mapping a region,locl a region,絕對位置讀取
    9. AIO Reactor(基於事件)和Proactor
 
  下面列一些示例:
 
2.1IO and New IO 監聽檔案系統變化通知
 
通過FileSystems.getDefault().newWatchService()獲取watchService,然後將需要監聽的path目錄註冊到這個watchservice中,對於這個目錄的檔案修改,新增,刪除等實踐可以配置,然後就自動能監聽到響應的事件。
 
    private WatchService watcher;
    public TestWatcherService(Path path) throws IOException {
    watcher = FileSystems.getDefault().newWatchService();
    path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
    }
    public void handleEvents() throws InterruptedException {
    while (true) {
    WatchKey key = watcher.take();
    for (WatchEvent<?> event : key.pollEvents()) {
    WatchEvent.Kind kind = event.kind();
    if (kind == OVERFLOW) {// 事件可能lost or discarded
    continue;
    }
    WatchEvent<Path> e = (WatchEvent<Path>) event;
    Path fileName = e.context();
    System.out.printf("Event %s has happened,which fileName is %s%n",kind.name(), fileName);
    }
    if (!key.reset()) {
    break;
    }
 
2.2 IO and New IO遍歷檔案樹 ,通過繼承SimpleFileVisitor類,實現事件遍歷目錄樹的操作,然後通過Files.walkFileTree(listDir, opts, Integer.MAX_VALUE, walk);這個API來遍歷目錄樹
 
    private void workFilePath() {
    Path listDir = Paths.get("/tmp"); // define the starting file
    ListTree walk = new ListTree();
    …Files.walkFileTree(listDir, walk);…
    // 遍歷的時候跟蹤連結
    EnumSet opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
    try {
    Files.walkFileTree(listDir, opts, Integer.MAX_VALUE, walk);
    } catch (IOException e) {
    System.err.println(e);
    }
    class ListTree extends SimpleFileVisitor<Path> {// NIO2 遞迴遍歷檔案目錄的介面
    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
    System.out.println("Visited directory: " + dir.toString());
    return FileVisitResult.CONTINUE;
    }
    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
    System.out.println(exc);
    return FileVisitResult.CONTINUE;
    }
    }
 
 
2.3 AIO非同步IO 檔案和網路 非同步IO在java
 NIO2實現了,都是用AsynchronousFileChannel,AsynchronousSocketChanne等實現,關於同步阻塞IO,同步非阻塞IO,非同步阻塞IO和非同步非阻塞IO在ppt的這頁上下面備註有說明,有興趣的可以深入瞭解下。Java NIO2中就實現了作業系統的非同步非阻塞IO。
 
    // 使用AsynchronousFileChannel.open(path, withOptions(),  
        // taskExecutor))這個API對非同步檔案IO的處理  
        public static void asyFileChannel2() {  
            final int THREADS = 5;  
            ExecutorService taskExecutor = Executors.newFixedThreadPool(THREADS);  
            String encoding = System.getProperty("file.encoding");  
            List<Future<ByteBuffer>> list = new ArrayList<>();  
            int sheeps = 0;  
            Path path = Paths.get("/tmp",  
                    "store.txt");  
            try (AsynchronousFileChannel asynchronousFileChannel = AsynchronousFileChannel  
                    .open(path, withOptions(), taskExecutor)) {  
                for (int i = 0; i < 50; i++) {  
                    Callable<ByteBuffer> worker = new Callable<ByteBuffer>() {  
                        @Override
                        public ByteBuffer call() throws Exception {  
                            ByteBuffer buffer = ByteBuffer  
                                    .allocateDirect(ThreadLocalRandom.current()  
                                            .nextInt(100, 200));  
                            asynchronousFileChannel.read(buffer, ThreadLocalRandom  
    ……
 
         
3. JDBC 4.1
 
3.1.可以使用try-with-resources自動關閉Connection, ResultSet, 和 Statement資源物件
 
3.2. RowSet 1.1:引入RowSetFactory介面和RowSetProvider類,可以建立JDBC driver支援的各種 row sets,這裡的rowset實現其實就是將sql語句上的一些操作轉為方法的操作,封裝了一些功能。
 
3.3. JDBC-ODBC驅動會在jdk8中刪除
 
    try (Statement stmt = con.createStatement()) {
     RowSetFactory aFactory = RowSetProvider.newFactory();
      CachedRowSet crs = aFactory.createCachedRowSet();
       
     RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null);
    WebRowSet wrs = rsf.createWebRowSet();
    createCachedRowSet
    createFilteredRowSet
    createJdbcRowSet
    createJoinRowSet
    createWebRowSet
 
 
4. 併發工具增強
 
4.1.fork-join
 最大的增強,充分利用多核特性,將大問題分解成各個子問題,由多個cpu可以同時解決多個子問題,最後合併結果,繼承RecursiveTask,實現compute方法,然後呼叫fork計算,最後用join合併結果。
 
    class Fibonacci extends RecursiveTask<Integer> {
    final int n;
    Fibonacci(int n) {
    this.n = n;
    }
    private int compute(int small) {
    final int[] results = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
    return results[small];
    }
    public Integer compute() {
    if (n <= 10) {
    return compute(n);
    }
    Fibonacci f1 = new Fibonacci(n - 1);
    Fibonacci f2 = new Fibonacci(n - 2);
    System.out.println("fork new thread for " + (n - 1));
    f1.fork();
    System.out.println("fork new thread for " + (n - 2));
    f2.fork();
    return f1.join() + f2.join();
    }
    }
 
 4.2.ThreadLocalRandon 併發下隨機數生成類,保證併發下的隨機數生成的執行緒安全,實際上就是使用threadlocal
 
    final int MAX = 100000;
    ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
    long start = System.nanoTime();
    for (int i = 0; i < MAX; i++) {
    threadLocalRandom.nextDouble();
    }
    long end = System.nanoTime() - start;
    System.out.println("use time1 : " + end);
    long start2 = System.nanoTime();
    for (int i = 0; i < MAX; i++) {
    Math.random();
    }
    long end2 = System.nanoTime() - start2;
    System.out.println("use time2 : " + end2);
 
        
4.3. phaser 類似cyclebarrier和countdownlatch,不過可以動態新增資源減少資源
 
     void runTasks(List<Runnable> tasks) {
    final Phaser phaser = new Phaser(1); // "1" to register self
    // create and start threads
    for (final Runnable task : tasks) {
    phaser.register();
    new Thread() {
    public void run() {
    phaser.arriveAndAwaitAdvance(); // await all creation
    task.run();
    }
    }.start();
    }
    // allow threads to start and deregister self
    phaser.arriveAndDeregister();
    }
 
5. Networking增強
 
新增URLClassLoader close方法,可以及時關閉資源,後續重新載入class檔案時不會導致資源被佔用或者無法釋放問題
URLClassLoader.newInstance(new URL[]{}).close();
新增Sockets Direct Protocol
繞過作業系統的資料拷貝,將資料從一臺機器的記憶體資料通過網路直接傳輸到另外一臺機器的記憶體中
 
6. Multithreaded Custom Class Loaders  
     
    解決併發下載入class可能導致的死鎖問題,這個是jdk1.6的一些新版本就解決了,jdk7也做了一些優化。有興趣可以仔細從官方文件詳細瞭解
 
jdk7前:
   
    Class Hierarchy:            
      class A extends B
      class C extends D
    ClassLoader Delegation Hierarchy:
    Custom Classloader CL1:
      directly loads class A
      delegates to custom ClassLoader CL2 for class B
    Custom Classloader CL2:
      directly loads class C
      delegates to custom ClassLoader CL1 for class D
    Thread 1:
      Use CL1 to load class A (locks CL1)
        defineClass A triggers
          loadClass B (try to lock CL2)
    Thread 2:
      Use CL2 to load class C (locks CL2)
        defineClass C triggers
          loadClass D (try to lock CL1)
    Synchronization in the ClassLoader class wa
 
jdk7
 
    Thread 1:
      Use CL1 to load class A (locks CL1+A)
        defineClass A triggers
          loadClass B (locks CL2+B)
    Thread 2:
      Use CL2 to load class C (locks CL2+C)
        defineClass C triggers
          loadClass D (locks CL1+D)
 
 
7. Security 增強
 
    7.1.提供幾種 ECC-based algorithms (ECDSA/ECDH) Elliptic Curve Cryptography (ECC)
    7.2.禁用CertPath Algorithm Disabling
    7.3. JSSE (SSL/TLS)的一些增強
 
8. Internationalization 增強 增加了對一些編碼的支援和增加了一些顯示方面的編碼設定等
     
    1. New Scripts and Characters from Unicode 6.0.0
    2. Extensible Support for ISO 4217 Currency Codes
    Currency類新增:      
           getAvailableCurrencies
           getNumericCode
           getDisplayName
           getDisplayName(Locale)
    3. Category Locale Support
     getDefault(Locale.Category)FORMAT  DISPLAY
    4. Locale Class Supports BCP47 and UTR35
           UNICODE_LOCALE_EXTENSION
           PRIVATE_USE_EXTENSION
           Locale.Builder
           getExtensionKeys()
           getExtension(char)
           getUnicodeLocaleType(String
            ……
    5. New NumericShaper Methods
    NumericShaper.Range
    getShaper(NumericShaper.Range)
    getContextualShaper(Set<NumericShaper.Range>)……
 
 
9.jvm方面的一些特性增強,下面這些特性有些在jdk6中已經存在,這裡做了一些優化和增強。
 
1.Jvm支援非java的語言 invokedynamic 指令
 
2. Garbage-First Collector 適合server端,多處理器下大記憶體,將heap分成大小相等的多個區域,mark階段檢測每個區域的存活物件,compress階段將存活物件最小的先做回收,這樣會騰出很多空閒區域,這樣併發回收其他區域就能減少停止時間,提高吞吐量。
 
3. HotSpot效能增強
    Tiered Compilation  -XX:+UseTieredCompilation 多層編譯,對於經常呼叫的程式碼會直接編譯程原生代碼,提高效率
   Compressed Oops  壓縮物件指標,減少空間使用
  Zero-Based Compressed Ordinary Object Pointers (oops) 進一步優化零基壓縮物件指標,進一步壓縮空間
 
4. Escape Analysis  逃逸分析,對於只是在一個方法使用的一些變數,可以直接將物件分配到棧上,方法執行完自動釋放記憶體,而不用通過棧的物件引用引用堆中的物件,那麼對於物件的回收可能不是那麼及時。
 
5. NUMA Collector Enhancements  
 
NUMA(Non Uniform Memory Access),NUMA在多種計算機系統中都得到實現,簡而言之,就是將記憶體分段訪問,類似於硬碟的RAID,Oracle中的分簇
 
10. Java 2D Enhancements
 
    1. XRender-Based Rendering Pipeline -Dsun.java2d.xrender=True
    2. Support for OpenType/CFF Fonts GraphicsEnvironment.getAvailableFontFamilyNames
    3. TextLayout Support for Tibetan Script
    4. Support for Linux Fonts
 
11. Swing Enhancements
 
    1.  JLayer
    2.  Nimbus Look & Feel
    3.  Heavyweight and Lightweight Components
    4.  Shaped and Translucent Windows
    5.  Hue-Saturation-Luminance (HSL) Color Selection in JColorChooser Class
 
 
 
12. Jdk8 lambda表示式 最大的新增的特性,不過在很多動態語言中都已經原生支援。
 
原來這麼寫:
 
    btn.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            System.out.println("Hello World!");
        }
    });
        
jdk8直接可以這麼寫:
 
    btn.setOnAction(
        event -> System.out.println("Hello World!")
    );   
        
更多示例:
    
    public class Utils {
        public static int compareByLength(String in, String out){
            return in.length() - out.length();
        }
    }
 
    public class MyClass {
        public void doSomething() {
            String[] args = new String[] {"microsoft","apple","linux","oracle"}
            Arrays.sort(args, Utils::compareByLength);
        }  
    }  
 
13.jdk8的一些其他特性,當然jdk8的增強功能還有很多,大家可以參考http://openjdk.java.net/projects/jdk8/
 
用Metaspace代替PermGen
動態擴充套件,可以設定最大值,限制於本地記憶體的大小
Parallel array sorting 新APIArrays#parallelSort.
 
    New Date & Time API
    Clock clock = Clock.systemUTC(); //return the current time based on your system clock and set to UTC.
 
    Clock clock = Clock.systemDefaultZone(); //return time based on system clock zone
 
    long time = clock.millis(); //time in milliseconds from January 1st, 1970