Java7新特性

jopen 12年前發布 | 23K 次閱讀 Java Java開發

特性1:二進制字面值(Binary Literals)

  在java7里,整形(byte,short,int,long)類型的值可以用二進制類型來表示了,在使用二進制的值時,需要在前面加上ob或oB,看代碼 

Java代碼 
  //b 大小寫都可以 
  int a = 0b01111_00000_11111_00000_10101_01010_10; 
  short b = (short)0b01100_00000_11111_0; 
  byte c = (byte)0B0000_0001; 

其次,二進制同十進制和十六進制相比,可以一目了然的看出數據間的關系。例如下面這個數組中展示了每次移動一位后數字的變化。 

Java代碼 
public static final int[] phases = { 
  0b00110001, 
  0b01100010, 
  0b11000100, 
  0b10001001, 
  0b00010011, 
  0b00100110, 
  0b01001100, 
  0b10011000 
}

如果用十六進制來表示的,它們之間的關系就無法一眼看出來了。 

public static final int[] phases = { 
  0x31, 0x62, 0xC4, 0x89, 0x13, 0x26, 0x4C, 0x98 

特性2:數字變量對下劃線_的支持

你可以在數值類型的變量里添加下滑線,除了以下的幾個地方不能添加: 
  數字的開頭和結尾 
  小數點前后 
  F或者L前 

需要出現string類型值的地方(針對用0x或0b表示十六進制和二進制,參考第一點),比如0x101,不能用0_x101 

  int num = 1234_5678_9; 
  float num2 = 222_33F; 
  long num3 = 123_000_111L; 

//下面的不行 
//數字開頭和結尾 
  int nu = _123; 
  int nu = 123_; 

//小數點前后 
float f = 123_.12; 
float f = 123._12; 

//F或者L前 
long l = 123_L; 
float f = 123_F; 

//需要出現String的地方 
int num = 0_b123; 
float f = 0_x123F; 

這個,我個人覺得沒什么實際作用,只是可以提升代碼的可讀性。


特性3:switch 對String的支持

這個大家期待很久了,switch終于支持String了 

public static void first() {   
    //項目狀態   
    String status = "approval";   
    //我們之前經常根據項目狀態不同來進行不同的操作   
    //目前已經換成enum類型   

    switch (status) {   
        case "shouli":   
            System.out.println("狀態是受理");   
            break;   
        case "approval":   
            System.out.println("狀態是審批");   
            break;   
        case "finish":   
            System.out.println("狀態是結束");   
            break;   
        default:   
            System.out.println("狀態未知");   
    }   
}   
    每個case是使用String的equals方法來進行比較的,對大小寫敏感。 
    和一連串的if-else-then想比,使用switch來比較String,Java編譯器會生成更加有效的字節碼,寫一個例子測試一下。 
Java代碼  
public static void second() {   
      String status = "approval";   
      if ("shouli".equals(status)) {   
          System.out.println("狀態是受理");   
      } else if ("approval".equals(status)) {   
          System.out.println("狀態是審批");   
      } else if ("finish".equals(status)) {   
          System.out.println("狀態是結束");   
      } else {   
          System.out.println("狀態未知");   
      }   
}   

使用javap之后,生成字節碼如下:(略)
網上說,用switch之后比用if-else生成的字節碼更有效一些,不過目前至少從長度上來說,switch還是長一些 

特性4:try-with-resources 聲明

  try-with-resources 是一個定義了一個或多個資源的try 聲明,這個資源是指程序處理完它之后需要關閉它的對象。try-with-resources 確保每一個資源在處理完成后都會被關閉。 
可以使用try-with-resources的資源有: 
任何實現了java.lang.AutoCloseable 接口和java.io.Closeable 接口的對象。

來看例子:

public static String readFirstLineFromFile(String path) throws IOException {   
     try (BufferedReader br = new BufferedReader(new FileReader(path))) {   
       return br.readLine();   
     }   
}   
   在java 7 以及以后的版本里,BufferedReader實現了java.lang.AutoCloseable接口。 

   由于BufferedReader定義在try-with-resources 聲明里,無論try語句正常還是異常的結束,
   它都會自動的關掉。而在java7以前,你需要使用finally塊來關掉這個對象。 

public static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {   
   BufferedReader br = new BufferedReader(new FileReader(path));   
   try {   
      return br.readLine();   
   } finally {   
      if (br != null) br.close();   
   }   
 }   
  然而,如果 readLine() 和 close() 這兩個方法都拋出異常,那么readFirstLineFromFileWithFinallyBlock 方法只會拋出后面部分也就是finally塊中的內容,try塊中的異常就被抑制了,對于我們的程序來說,這顯然不是一種好的方式。 

  而在java 7中,無論是try塊還是try-with-resource中拋出異常,都能捕捉到。 有 

另外,一個try-with-resourcse聲明了可以包含多個對象的聲明,用分號隔開,和聲明一個對象相同,會在結束后自動調用close方法,調用順序和生命順序相反。 

try ( 
  java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName); 
  java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset) 
) { 
// do something 


此外,try-with-resources 可以跟catch和finally,catch和finally的是在try-with-resources里聲明的對象關閉之后才執行的。 

特性5:捕獲多種異常并用改進后的類型檢查來重新拋出異常 

1、捕獲多種異常

在Java SE7里,一個catch可以捕獲多個異常,這樣可以減少重復代碼。每個異常之間用 | 隔開。

public static void first(){   
 try {   
  BufferedReader reader = new BufferedReader(new FileReader(""));   
  Connection con = null;   
  Statement stmt = con.createStatement();   
 } catch (IOException | SQLException e) {   
   //捕獲多個異常,e就是final類型的   
   e.printStackTrace();   
    }   
}   
   而在Java SE6以前,需要這樣寫 
   Java代碼  
      public static void second() {   
  try {   
    BufferedReader reader = new BufferedReader(new FileReader(""));   
    Connection con = null;   
    Statement stmt = con.createStatement();   
  } catch (IOException e) {   
        e.printStackTrace();   
    } catch (SQLException e) {   
        e.printStackTrace();   
    }   
}   
     
   注意,如果一個catch處理了多個異常,那么這個catch的參數默認就是final的,你不能在catch塊里修改它的值。 
另外,用一個catch處理多個異常,比用多個catch每個處理一個異常生成的字節碼要更小更高效。 

2、用更包容性的類型檢查來重新拋出異常

在方法的聲明上,使用throws語句時,你可以指定更加詳細的異常類型。

static class FirstException extends Exception { }   
static class SecondException extends Exception { }   

public void rethrowException(String exceptionName) throws Exception {   
  try {   
     if (exceptionName.equals("First")) {   
         throw new FirstException();   
     } else {   
         throw new SecondException();   
     }   
  } catch (Exception e) {   
   throw e;   
  }   
 }   
  

這個例子,try塊中只能拋出兩種異常,但是因為catch里的類型是 Exception,在java SE7以前的版本中,在方法聲明中throws 只能寫Exception,但是在java SE7及以后的版本中,可以在throws后面寫 FirstException和SecondException——編譯器能判斷出throw e語句拋出的異常一定來自try塊,并且try塊只能拋出FirstException和SecondException。

public static void reThrowException(String exceptionName) throws FirstException, SecondException{   
 try {   
    if ("first".equals(exceptionName))   
       throw new FirstException();   
    else   
       throw new SecondException();   
 } catch (Exception e) {   
       throw e;   
 }   
}   

所以盡管catch里的異常類型是Exception,編譯器仍然能夠知道它是FirstException和 SecondException的實例。怎么樣,編譯器變得更智能了吧。

但是,如果在catch里對異常重新賦值了,在方法的throws后無法再象上面那樣寫成FirstException和SecondException了,而需要寫成 Exception。

具體來說,在Java SE 7及以后版本中,當你在catch語句里聲明了一個或多個異常類型,并且在catch塊里重新拋出了這些異常,編譯器根據下面幾個條件來去核實異常的類型: 

- Try塊里拋出它 
- 前面沒有catch塊處理它 
- 它是catch里一個異常類型的父類或子類。

特性6:創建泛型對象時類型推斷

   只要編譯器可以從上下文中推斷出類型參數,你就可以用一對空著的尖括號<>來代替泛型參數。這對括號私下被稱為菱形(diamond)。 在Java SE 7之前,你聲明泛型對象時要這樣

List<String> list = new ArrayList<String>(); 

而在Java SE7以后,你可以這樣 

List<String> list = new ArrayList<>(); 
  因為編譯器可以從前面(List)推斷出推斷出類型參數,所以后面的ArrayList之后可以不用寫泛型參數了,只用一對空著的尖括號就行。當然,你必須帶著”菱形”<>,否則會有警告的。 

Java SE7 只支持有限的類型推斷:只有構造器的參數化類型在上下文中被顯著的聲明了,你才可以使用類型推斷,否則不行。 

List<String> list = new ArrayList<>(); 
list.add("A"); 

//這個不行 
list.addAll(new ArrayList<>()); 

// 這個可以 
List<? extends String> list2 = new ArrayList<>(); 
list.addAll(list2);

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!