Java Development Kit (JDK) 發展歷程 及新特性

   SE(J2SE),standard edition,標準版,是咱們一般用的一個版本,從JDK 5.0開始,更名爲Java SE。html

      EE(J2EE),enterprise edition,企業版,使用這種JDK開發J2EE應用程序,從JDK 5.0開始,更名爲Java EE。java

      ME(J2ME),micro edition,主要用於移動設備、嵌入式設備上的java應用程序,從JDK 5.0開始,更名爲Java ME。git

      沒有JDK的話,沒法編譯Java程序,若是想只運行Java程序,要確保已安裝相應的JRE程序員

      如下是各版本的名稱及發佈日期:數據庫

版本編程

名稱瀏覽器

發行日期安全

JDK 1.1.4服務器

Sparkler(寶石)網絡

1997-09-12

JDK 1.1.5

Pumpkin(南瓜)

1997-12-13

JDK 1.1.6

Abigail(阿比蓋爾–女子名)

1998-04-24

JDK 1.1.7

Brutus(布魯圖–古羅馬政治家和將軍)

1998-09-28

JDK 1.1.8

Chelsea(切爾西–城市名)

1999-04-08

J2SE 1.2

Playground(運動場)

1998-12-04

J2SE 1.2.1

none(無)

1999-03-30

J2SE 1.2.2

Cricket(蟋蟀

1999-07-08

J2SE 1.3

Kestrel(美洲紅隼)

2000-05-08

J2SE 1.3.1

Ladybird(瓢蟲)

2001-05-17

J2SE 1.4.0

Merlin(灰背隼)

2002-02-13

J2SE 1.4.1

grasshopper(蚱蜢)

2002-09-16

J2SE 1.4.2

Mantis(螳螂

2003-06-26

Java SE 5.0 (1.5.0)

Tiger(老虎)

2004-09-30

Java SE 6.0 (1.6.0)

Mustang(野馬)

2006-04

Java SE 7.0 (1.7.0)

Dolphin(海豚)

2011-07-28

Java SE 8.0 (1.8.0)

未知

2013-09(預約)

 

 
 
參考:
 

 
 
  
「JDK1.5」(開發代號猛虎)的新特性
 
1.泛型(Generic)

  C++經過模板技術 能夠指定集合的元素類型,而Java在1.5以前一直沒有相對應的功能。一個集合能夠聽任何類型的對象,相應地從集合裏面拿對象的時候咱們也不得不對他們 進行強制得類型轉換。猛虎引入了泛型,它容許指定集合裏元素的類型,這樣你能夠獲得強類型在編譯時刻進行類型檢查的好處。

 
Collection<String> c = new ArrayList();
c.add(new Date());


  編譯器會給出一個錯誤:

add(java.lang.String) in java.util.Collection<java.lang.String> cannot be applied to (java.util.Date)


  2.For-Each循環

  For-Each循環得加入簡化了集合的遍歷。假設咱們要遍歷一個集合對其中的元素進行一些處理。典型的代碼爲:

void processAll(Collection c){
    for(Iterator i=c.iterator(); i.hasNext();){
        MyClass myObject = (MyClass)i.next();
        myObject.process();
    }
}


  使用For-Each循環,咱們能夠把代碼改寫成:

void processAll(Collection<MyClass> c){
    for (MyClass  myObject :c)
        myObject.process();
}


  這段代碼要比上面清晰許多,而且避免了強制類型轉換。

  3.自動裝包/拆包(Autoboxing/unboxing)

  自動裝包/拆包大大方便了基本類型數據和它們包裝類地使用。

  自動裝包:基本類型自動轉爲包裝類.(int >> Integer)

  自動拆包:包裝類自動轉爲基本類型.(Integer >> int)

  在JDK1.5以前,咱們老是對集合不能存放基本類型而耿耿於懷,如今自動轉換機制解決了咱們的問題。

int a = 3;
Collection c = new ArrayList();
c.add(a);//自動轉換成Integer.

Integer b = new Integer(2);
c.add(b + 2);

  這裏Integer先自動轉換爲int進行加法運算,而後int再次轉換爲Integer.

   4.枚舉(Enums)

  JDK1.5加入了一個全新類型的「類」-枚舉類型。爲此JDK1.5引入了一個新關鍵字enmu. 咱們能夠這樣來定義一個枚舉類型。
 
public enum Color
{
   Red,
   White,
   Blue
}

  而後能夠這樣來使用Color myColor = Color.Red.

  枚舉類型還提供了兩個有用的靜態方法values()和valueOf(). 咱們能夠很方便地使用它們,例如

for (Color c : Color.values())
            System.out.println(c);

   5.可變參數(Varargs)

  可變參數使程序員能夠聲明一個接受可變數目參數的方法。注意,可變參數必須是函數聲明中的最後一個參數。假設咱們要寫一個簡單的方法打印一些對象,

util.write(obj1);
util.write(obj1,obj2);
util.write(obj1,obj2,obj3);

  在JDK1.5以前,咱們能夠用重載來實現,可是這樣就須要寫不少的重載函數,顯得不是頗有效。若是使用可變參數的話咱們只須要一個函數就好了

public void write(Object... objs) {
   for (Object obj: objs)
      System.out.println(obj);
}

   在引入可變參數之後,Java的反射包也更加方便使用了。對於c.getMethod("test", new  Object[0]).invoke(c.newInstance(), new Object[0])),如今咱們能夠這樣寫了 c.getMethod("test").invoke(c.newInstance()),這樣的代碼比原來清楚了不少。 

   6.靜態導入(Static Imports)

  要使用用靜態成員(方法和變量)咱們必須給出提供這個方法的類。使用靜態導入可使被導入類的全部靜態變量和靜態方法在當前類直接可見,使用這些靜態成員無需再給出他們的類名。

import static java.lang.Math.*;
…….
r = sin(PI * 2); //無需再寫r = Math.sin(Math.PI);

  不過,過分使用這個特性也會必定程度上下降代碼地可讀性。
Collection<String> c = new ArrayList();
c.add(new Date());


  編譯器會給出一個錯誤:

add(java.lang.String) in java.util.Collection<java.lang.String> cannot be applied to (java.util.Date)





Java SE 6.0 (1.6.0)

Mustang(野馬)的新特性

簡化Web Services
Mustang 將 簡化Web services 的開發和發佈. XML和Web服務一直都是Mustang的關注重點.. Mustang爲此引入了JAX-WS(Java Architecture for XML-Web Services) 2.0 以及JAXB(Java Architecture for XML Binding) 2.0.. 同時還有Streaming API for XML (STaX), 它提供了一個雙向API,這個API能夠經過一個事件流來讀取或者寫入XML,其中包括跳過某個部分,而後直接關注與文檔中的另一個小部分的能力。


Scripting,整合腳本語言
目前來說,Java 開發者們必須在Java以外獨立地額外編碼來使用non-Java 腳本語言。這個頭痛的問題將被Mustang 消滅,開發者將更加輕鬆的使用Perl、PHP、Python、JavaScript 和Ruby等腳本語言。新的框架將容許人們操做任意的腳本語言,和使用Java 對象。

Java SE6中實現了JSR223。這是一個腳本框架,提供了讓腳本語言來訪問Java內部的方法。你能夠在運行的時候找到腳本引擎,而後調用這個引擎去執行腳本。這個腳本API容許你爲腳本語言提供Java支持。另外,Web Scripting Framework容許腳本代碼在任何的Servlet容器(例如Tomcat)中生成Web內容。

Database,綁定Derby
開源嵌入式數據庫 Derby(JavaDB) 綁定在JDK 1.6中.具體能夠參考:JDK 1.6 將綁定開源數據庫 Derby

更豐富的Desktop APIs
Mustang中擁有更多強的桌面API提供給開發者, 開發者能夠更簡單地開發更強大的桌面應用, 好比啓動界面的支持,系統托盤的支持,JTable排序等等

監視和管理
Java SE 6中對內存泄漏加強了分析以及診斷能力。當遇到java.lang.OutOfMemory異常的時候,能夠獲得一個完整的堆棧信息,而且當堆已經滿了的時候,會產生一個Log文件來記錄這個致命錯誤。另外,JVM還添加了一個選項,容許你在堆滿的時候運行腳本。(這也就是提供了另一種方法來診斷錯誤)

加強的JMX 監視API在MBean的屬性值傳入了一個特定的參數的時候,容許這個應用程序發送一個事件通告。(這裏的屬性值能夠在很複雜的類型中)

對於Solaris 10的用戶,爲Solaris提供的Hotspot JVM中,提供了一種經過Solaris DTrace(這是個系統的調試工具)來追蹤顯示JVM內部的活動狀況,包括垃圾收集,類裝載,線程,鎖等等。

Pluggable Annotations
從Java SE 5   帶來得新特性Annotations,將在Mustang繼續扮演重要角色..

Compiler API:訪問編譯器
對於Java開發工具, 或者Web框架 等的開發者來講, 利用編譯器編譯動態生成的代碼, 是一個廣泛的需求.

Mustang實現了JSR 199,   提供了Java編譯器API(應用程序接口),容許你從一個Java應用程序中去編譯其餘的Java源程序--好比在應用程序中動態生成的一些源代碼..

Security:安全性
Java SE 6的安所有分,增長了 XML-Digital Signature (XML-DSIG) APIs, 整合了GSS/Kerberos的操做API,LDAP上的JAAS認證。

Instrumentation
      利用 Java 代碼,即 java.lang.instrument 作動態 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能從本地代碼中解放出來,使之能夠用 Java 代碼的方式解決問題。在 Java SE 6 裏面,instrumentation 包被賦予了更強大的功能:啓動後的 instrument、本地代碼(native code)instrument,以及動態改變 classpath 等等。在 Java SE 5 當中,開發者只能在 premain 當中施展想象力,所做的 Instrumentation 也僅限與 main 函數執行前,這樣的方式存在必定的侷限性。在 Java SE 6 的 Instrumentation 當中,有一個跟 premain「並駕齊驅」的「agentmain」方法,能夠在 main 函數開始運行以後再運行。

Http
    在 Java SE 6 當中,圍繞着 HTTP 協議出現了不少實用的新特性:NTLM 認證提供了一種 Window 平臺下較爲安全的認證機制;JDK 當中提供了一個輕量級的 HTTP 服務器;提供了較爲完善的 HTTP Cookie 管理功能;更爲實用的 NetworkInterface;DNS 域名的國際化支持等等。
    HTTP Cookie管理能夠應用客戶操做臨時變量的保存,如查詢條件,當前狀態等


JMX與系統管理

Agent / SubAgent 起到的就是翻譯的做用:把 IT 資源報告的消息以管理系統能理解的方式傳送出去。

也許讀者有會問,爲何須要 Agent 和 SubAgent 兩層體系呢?這裏有兩個現實的緣由:

管理系統通常是一箇中央控制的控制軟件,而 SubAgent 直接監控一些資源,每每和這些資源分佈在同一物理位置。當這些 SubAgent 把狀態信息傳輸到管理系統或者傳達管理系統的控制指令的時候,須要提供一些網絡傳輸的功能。

  1. 管理系統的消息是有必定規範的,消息的翻譯自己是件複雜而枯燥的事情。

通常來講,管理系統會將同一物理分佈或者功能相似的 SubAgent 分組成一組,由一個共用的 Agent 加以管理。在這個 Agent 裏封裝了 1 和 2 的功能。

JMX 和管理系統

JMX 既是 Java 管理系統的一個標準,一個規範,也是一個接口,一個框架

JMX 是管理系統和資源之間的一個接口,它定義了管理系統和資源之間交互的標準。javax.management.MBeanServer 實現了 Agent 的功能,以標準的方式給出了管理系統訪問 JMX 框架的接口。而 javax.management.MBeans 實現了 SubAgent 的功能,以標準的方式給出了 JMX 框架訪問資源的接口。而從類庫的層次上看,JMX 包括了核心類庫 java.lang.management 和 javax.management 包。java.lang.management 包提供了基本的 VM 監控功能,而 javax.management 包則向用戶提供了擴展功能。 JMX幫助開發者監控JVM的信息。

編輯器API

     JDK 6 提供了在運行時調用編譯器的 API。在傳統的 JSP 技術中,服務器處理 JSP 一般須要進行下面 6 個步驟:

  1. 分析 JSP 代碼;
  2. 生成 Java 代碼;
  3. 將 Java 代碼寫入存儲器;
  4. 啓動另一個進程並運行編譯器編譯 Java 代碼;
  5. 將類文件寫入存儲器;
  6. 服務器讀入類文件並運行;

     但若是採用運行時編譯,能夠同時簡化步驟 4 和 5,節約新進程的開銷和寫入存儲器的輸出開銷,提升系統效率。實際上,在 JDK 5 中,Sun 也提供了調用編譯器的編程接口。然而不一樣的是,老版本的編程接口並非標準 API 的一部分,而是做爲 Sun 的專有實現提供的,而新版則帶來了標準化的優勢。
     新 API 的第二個新特性是能夠編譯抽象文件,理論上是任何形式的對象 —— 只要該對象實現了特定的接口。有了這個特性,上述例子中的步驟 3 也能夠省略。整個 JSP 的編譯運行在一個進程中完成,同時消除額外的輸入輸出操做。
     第三個新特性是能夠收集編譯時的診斷信息。做爲對前兩個新特性的補充,它可使開發人員輕鬆的輸出必要的編譯錯誤或者是警告信息,從而省去了不少重定向的麻煩

一些有趣的新特性:

1 本地行爲 java.awt.Desktop
好比用默認程序打開文件,用默認瀏覽器打開url,不再用那個browserlauncher那麼費勁

Desktop desk=Desktop.getDesktop();
desk.browse(new URI(" http://www.google.com/"));
desk.open(file)
desk.print(file)

2 console下密碼輸入 java.io.Console
不再用本身寫線程去刪echo字符了
Console console = System.console();
char password[] = console.readPassword("Enter password: ");

3 獲取磁盤空間大小 java.io.File的新方法
File roots[] = File.listRoots();
for (File root : roots) {
System.out.println(root.getPath()+":"+root.getUsableSpace()
+"/"+root.getTotalSpace());
}

4 專利過時,能夠提供合法的lzw的gif encoder了
ImageIO.write(input, "GIF", outputFile);

5 JAXB2.0 增長了java-to-xml schema,完成java bean,xml間轉換很是容易

6 xml數字簽名 javax.xml.crypto,記得之前彷佛只有ibm有個類庫實現了

7 編譯器,之前是com.sun.tools.javac,如今是javax.tools.JavaCompiler
有人寫了徹底在內存裏的生成源文件,編譯,反射運行的過程,比較好玩。

8 腳本引擎,javax.script,內嵌的是Mozilla Rhino1.6r2 支持ECMAScript1.6
 

Java SE 7.0 (1.7.0)

Dolphin(海豚)的新特性

一、Switch中可使用String了

  在以前的版本中是不支持在Switch語句塊中用String類型的數據的,這個功能在C#語言中早已被支持,好在JDK1.7中加入了。

String s = "test";   
switch (s) {   
  case "test" :   
     System.out.println("test");  
  case "test1" :   
    System.out.println("test1"); 
    break ;   
  default :   
    System.out.println("break"); 
    break ;   
 }

二、泛型實例化類型自動推斷

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

三、對Java 集合( Collections )的加強支持

  在JDK1.7以前的版本中,Java集合容器中存取元素的形式以下。以List、Set、Map集合容器爲例:

//建立List接口對象  
List<String> list=new ArrayList<String>();  
list.add("item"); //用add()方法獲取對象  
String Item=list.get(0); //用get()方法獲取對象  

//建立Set接口對象  
Set<String> set=new HashSet<String>();  
set.add("item"); //用add()方法添加對象  

//建立Map接口對象  
Map<String,Integer> map=new HashMap<String,Integer>();  
map.put("key",1); //用put()方法添加對象  int value=map.get("key")  

  在JDK1.7 中,摒棄了 Java 集合接口的實現類,如: ArrayList 、 HashSet 和 HashMap 。而是直接採用 [] 、{} 的形式存入對象,採用 [] 的形式按照索引、鍵值來獲取集合中的對象,以下: 

List<String> list=["item"]; //向List集合中添加元素  
String item=list[0]; //從List集合中獲取元素  
Set<String> set={"item"}; //向Set集合對象中添加元素  
Map<String,Integer> map={name:"xxx",age:18}; //向Map集合中添加對象  int value=map["age"]; //從Map集合中獲取對象  

四、新增一些取環境信息的工具方法

File System.getJavaIoTempDir() // IO臨時文件夾
File System.getJavaHomeDir() // JRE的安裝目錄
File System.getUserHomeDir() // 當前用戶目錄
File System.getUserDir() // 啓動java進程時所在的目錄
……

五、Boolean類型反轉,空指針安全,參與位運算

//類型反轉,空指針安全
Boolean Booleans.negate(Boolean booleanObj) //True => False , False => True, Null => Null
//參與位運算boolean Booleans.and(boolean[] array) 
boolean Booleans.or(boolean[] array) 
boolean Booleans.xor(boolean[] array) 
boolean Booleans.and(Boolean[] array) 
boolean Booleans.or(Boolean[] array) 
boolean Booleans.xor(Boolean[] array)

六、兩個char間的equals

boolean Character.equalsIgnoreCase(char ch1, char ch2)

七、安全的加減乘除

int Math.safeToInt(long value)
int Math.safeNegate(int value)
long Math.safeSubtract(long value1, int value2)
long Math.safeSubtract(long value1, long value2)
int Math.safeMultiply(int value1, int value2)
long Math.safeMultiply(long value1, int value2)
long Math.safeMultiply(long value1, long value2)
long Math.safeNegate(long value)
int Math.safeAdd(int value1, int value2)
long Math.safeAdd(long value1, int value2)
long Math.safeAdd(long value1, long value2)
int  Math.safeSubtract(int value1, int value2)

八、數值可加下劃線

int one_million = 1_000_000;

九、支持二進制文字

int binary = 0b1001_1001;
 
   

1. 能夠用二進制表達數字

能夠用二進制表達數字(加前綴0b/0B),包括:byte, short, int, long

複製代碼
    // 能夠用二進制表達數字(加前綴0b/0B),包括:byte, short, int, long    @Test
    public void testLiterals() {
        // An 8-bit 'byte' value:
        byte aByte = (byte)0b00100001;
        
        // A 16-bit 'short' value:
        short aShort = (short)0b1010000101000101;

        // Some 32-bit 'int' values:
        int anInt1 = 0b10100001010001011010000101000101;
        int anInt2 = 0b101;
        int anInt3 = 0B101; // The B can be upper or lower case.

        // A 64-bit 'long' value. Note the "L" suffix:
        long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;
        
        // 來個簡單版本的
        byte b = 0b10;
        short s = 0B100;
        int i = 0b1000;
        long l = 0B10000;
        
        System.out.println(b + "|" + s + "|" + i + "|" + l);
        // ->輸出將會是2|4|8|16
    }
複製代碼

2. 能夠對數字加下劃線

能夠對數字加下劃線以讓變量表達得更清楚些;注意:符號「.」左右不能夠用下劃線、還包括「L/F/0x"等等。

複製代碼
    // 能夠對數字加下劃線以讓變量表達得更清楚些
    // 注意:符號「.」左右不能夠用下劃線、還包括「L/F/0x"等等。    @Test
    public void testUnderscores() {
        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;
        
        System.out.println(creditCardNumber + "|" + socialSecurityNumber);
        // ->下劃線僅供代碼中直觀查看,輸出時自動去掉了;輸出將會是:1234567890123456|999999999
    }
複製代碼

3. switch中可使用字符串了

複製代碼
    // switch中可使用字符串了 
    public 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;
    }
複製代碼

4. 泛型實例化類型自動推斷

複製代碼
    // 泛型實例化類型自動推斷    @Test
    public void testGeneric() {
        // 舊版本
        Map<String, List<String>> myMap1 = new HashMap<String, List<String>>();
        
        // 新版本
        Map<String, List<String>> myMap2 = new HashMap<>();
        
        List<String> list = new ArrayList<>();
        list.add("A");
        
        // 下面這條語句編譯不過;若是改爲:new ArrayList<String>()則能夠。
//        list.addAll(new ArrayList<>());
    }
複製代碼

5. 「非安全操做」的警告

 當使用一個不可具體化的參數(Non-Reifiable Formal Parameters)調用一個可變參數方法(Varargs Methods )編輯器會生成一個「非安全操做」的警告。

複製代碼
package com.clzhang.sample.thinking;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;

/**
 * 當使用一個不可具體化的參數(Non-Reifiable Formal Parameters)調用一個可變參數方法(Varargs Methods )
 * 編輯器會生成一個「非安全操做」的警告。
 * @author acer
 *
 */public class ArrayBuilder {
    //Type safety: Potential heap pollution via varargs parameter elements
    public static <T> void addToList(List<T> listArg, T... elements) {
        for (T x : elements) {
            listArg.add(x);
        }
    }

    //Type safety: Potential heap pollution via varargs parameter l    @SafeVarargs
    public static void faultyMethod(List<String>... l) {
        Object[] objectArray = l; // Valid
        
        // 這一行代碼把列表中的數據類型給改變了!
        objectArray[0] = Arrays.asList(new Integer(42));
        
        // 下面再取值,會報錯;由於裏面已經再也不是String類型的數據,而是Integer類型的數據。
        String s = l[0].get(0); // ClassCastException thrown here
        
        // 若是註釋掉本方法中的第2行代碼,則此條語句能夠執行;不然,執行不到這裏。
        System.out.println("first param is:" + s);
    }

    @Test
    public void testHeapPollution() {
        List<String> stringListA = new ArrayList<String>();
        List<String> stringListB = new ArrayList<String>();

        ArrayBuilder.addToList(stringListA, "Seven", "Eight", "Nine");
        ArrayBuilder.addToList(stringListA, "Ten", "Eleven", "Twelve");
        List<List<String>> listOfStringLists = new ArrayList<List<String>>();
        ArrayBuilder.addToList(listOfStringLists, stringListA, stringListB);

        ArrayBuilder.faultyMethod(Arrays.asList("Hello!"), Arrays.asList("World!"));
    }
}
複製代碼

6. 對資源的自動回收管理

複製代碼
    // JDK1.7以前的作法,須要在finally塊中關閉相關資源
    String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(path));
        try {
            return br.readLine();
        } finally {
            if (br != null)
                br.close();
        }
    }

    // JDK1.7中已經不須要手工關閉這些資源了,JRE自動關閉這些資源。
    // 一個對象實現了java.lang.AutoCloseable接口,或者是包含的全部對象實現了java.io.Closeable接口,便可以做爲一個資源來使用。
    String readFirstLineFromFile(String path) throws IOException {
        try (BufferedReader br = new BufferedReader(new FileReader(path))) {
            return br.readLine();
        }
    }

    @Test
    public void testAutoClose() throws Exception {
        String path = "D:\\TDDOWNLOAD\\readme.txt";
        
        System.out.println(readFirstLineFromFileWithFinallyBlock(path));
        System.out.println(readFirstLineFromFile(path));
    }
複製代碼

7. 多個異常的合併與重拋異常的檢查

7.1 捕捉多個異常

看下面這段代碼:

複製代碼
catch (IOException ex) {
     logger.log(ex);
     throw ex;
catch (SQLException ex) {
     logger.log(ex);
     throw ex;
}
複製代碼

在JDK1.7中,上述代碼能夠改寫爲:

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

7.2 重拋異常

看下面這段代碼:

複製代碼
  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;
    }
  }
複製代碼

在以前 JDK版本中,它不能夠:throws FirstException, SecondException。而在JDK1.7中,它能夠了,以下:

複製代碼
  public void rethrowException(String exceptionName)
  throws FirstException, SecondException {
    try {
      // ...    }
    catch (Exception e) {
      throw e;
    }
  }
複製代碼
 
注意:try/catch中throw的是Exception,但在函數頭中,倒是:throws  FirstException, SecondException。這在以前的版本中編譯是通不過的。
相關文章
相關標籤/搜索