JDK1.5,JDK1.6,JDK1.7 各自的新特性

JDK1.5(JDK5.0)

Java2標準版(Java 2 Platform, Standard Edition, J2SE)1.5版本更新不同於以往,它帶來了很多里程碑式的革新,SUN將其綽號取名爲“虎”。這一次的變革將是Java誕生以來從未有過的,它給我們帶來了耳目一新的感覺。下面我們就來欣賞一下其中的部分典型變化:

 

比較JDK版本,JDK 1.5中新增的語言特性:

1.枚舉(增加了一個關鍵字enum);

2.變參(方法參數數量可以不固定多少);

3.泛型;

4.自動拆裝箱(基本類型與包裝類型可以混用);

5.foreach循環(方法地用於遍歷數組和集合);

6.靜態導入(可以在使用靜方法前不加類名);

7.註釋(採用@前綴,這個基本上是爲了簡化J2EE而準備的,在JavaEE5中的EJB3、JPA等中隨處可以看到它的身影)。

在JVM、基本類庫、SDK工具和硬件平臺支持上都有很多的提高,這個JDK版本的出現可以說是Java中的一次飛越。

具體的解釋下:

1.自動包裝和解包(Autoboxing and unboxing)
  代碼示例
  
  往一個ArrayList中加入一個整數,1.5版本以前的版本寫法是:
  
  List list = new ArrayList();
  
  list.add( new Integer( 10 ) );
  
  而在1.5版本中可以寫爲:
  
  list.add( 10 );
  
  因爲,在1.5版本中,對一個整數進行包裝,使之成爲一個Integer對象(即包裝,boxing),然後加入到一個ArrayList中的做法被認爲是沒有必要的,反之,解包(unboxing)的做法也是沒有必要的,這樣的代碼只是增加了程序的文本長度而已,所以1.5版本支持了自動包裝和解包操作,對於bool/Boolean,byte/Byte,double/Double,short/Short,int/Integer,long/Long,float/Float的相應包裝/解包操作都進行了支持,從而使代碼變得簡單。
  
  2.更優化的循環語句(The inhanced for loop)
  代碼示例
  
  一個典型的遍歷數組的循環語句,1.5版本以前的寫法是:
  
  for ( Iterator iterator = list.iterator(); iterator.hasNext(); )
  
  {
  
  Integer n = (Integer)iterator.next();
  
  ...
  
  }//for
  
  而在1.5版本中可以寫爲:
  
  for ( Integer n : list )
  
  {
  
  ...
  
  }//for
  
  顯然1.5版本的寫法比以前是大大簡化了,但是在需要修改集合,比如刪除其中元素時不能採用這種寫法。之所以Java1.5版本沒有象C#那樣乾脆定義一個foreach關鍵詞,主要是因爲SUN認爲增加一個專門的關鍵詞成本太高了(too costly)。但1.4版本中就曾經增加了assert關鍵詞,1.5版本中也新增加了enum關鍵詞,因此這一解釋恐怕並不那麼令人信服。
  
  3.參數可變的方法和printf
  代碼示例
  
  當不能確定一個方法的入口參數的個數時,以往版本的Java中,通常的做法是將多個參數放在一個數組或者對象集合中作爲參數來傳遞,1.5版本以前的寫法是:
  
  int sum(Integer[] numbers)
  
  {
  
  int nSum = 0;
  
  for(int i: numbers)
  
  nSum += i;
  
  return nSum;
  
  }
  
  ...
  
  //在別處調用該方法
  
  sum(new Integer[] {12,13,20});
  
  而在1.5版本中可以寫爲:
  
  int sum(Integer... numbers)
  
  {
  
  int nSum = 0;
  
  for(int i: numbers)
  
  nSum += i;
  
  return nSum;
  
  }
  
  ...
  
  //在別處調用該方法
  
  sum(12,13,20);
  
  顯然,1.5版本的寫法更爲簡易,也更爲直觀,尤其是方法的調用語句,不僅簡化很多,而且更符合通常的思維方式,更易於理解。
  
  1.5版本自身就有一個應用該特徵的典型例子,即C風格的格式化輸出方法——printf。
  
  代碼示例
  
  輸出一個加法算式,1.5版本以前的寫法是:
  
  int x = 5;
  
  int y = 7;
  
  int nSum = x + y;
  
  System.out.println(x + " + " + y + " = " + nSum);
  
  而在1.5版本中可以寫爲:
  
  System.out.printf("%d + %d = %d\n", x, y, nSum);
  
  以上兩種寫法的輸出結構是一樣的,即“5 + 7 = 12”。
  
  這種改變不僅僅是形式上的,printf還可以提供更爲靈活、強大的輸出功能,比如限定按照兩位整數的形式輸出,可以寫爲“System.out.printf("%02d + %02d = %02d\n", x, y, nSum);”,輸出結果將是“05 + 07 = 12”。
  
  4.枚舉
  代碼示例
  
  構建一個表示色彩的枚舉,並賦值,在1.5版本中可以寫爲:
  
  public enum MyColor{ Red, Yellow, Blue }
  
  MyColor color = MyColor.Red;
  
  for ( MyColor mycolor : MyColor.values() )
  
  System.out.println( mycolor );
  
  以往的Java版本中沒有enum關鍵詞,1.5版本中終於加入了進來,這確實是一個令人高興的改進。此外,enum還提供了一個名爲values()的靜態方法,用以返回枚舉的所有值的集合。所以,以上程序的輸出結果是把“Red”、“Yellow”、“Blue”分行輸出。
  
  而enum提供的靜態方法valueOf()則將以字符串的形式返回某一個具體枚舉元素的值,比如“MyColor.valueOf(“Red”)”會返回“Color.Red”。靜態方法name()則返回某一個具體枚舉元素的名字,比如“MyColor.Red.name()”會返回“Red”。類似的方法還有不少。此外,enum自身還可以有構造方法。
  
  5.靜態引用
  代碼示例
  
  當我們要獲取一個隨即數時,1.5版本以前的寫法是:
  
  import java.lang.Math; //程序開頭處
  
  ...
  
  double x = Math.random();
  
  而在1.5版本中可以寫爲:
  
  import static java.lang.Math.random; //程序開頭處
  
  …
  
  double x = random();
  
  靜態引用使我們可以象調用本地方法一樣調用一個引入的方法,當我們需要引入同一個類的多個方法時,只需寫爲“import static java.lang.Math.*”即可。這樣的引用方式對於枚舉也同樣有效。

 

 

 

JDK1.6

簡化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與系統管理

管理系統的構架
圖 1. 管理系統構架

 

上圖分析了管理系統的基本構架模式。其中 Agent / SubAgent 起到的就是翻譯的作用:把 IT 資源報告的消息以管理系統能理解的方式傳送出去。

也許讀者有會問,爲什麼需要 Agent 和 SubAgent 兩層體系呢?這裏有兩個現實的原因:

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

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

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

JMX 和管理系統

JMX 既是 Java 管理系統的一個標準,一個規範,也是一個接口,一個框架。圖 2 展示了 JMX 的基本架構。
圖 2. JMX 構架和其它的資源系統一樣,JMX 是管理系統和資源之間的一個接口,它定義了管理系統和資源之間交互的標準。javax.management.MBeanServer 實現了 Agent 的功能,以標準的方式給出了管理系統訪問 JMX 框架的接口。而javax.management.MBeans 實現了 SubAgent 的功能,以標準的方式給出了 JMX 框架訪問資源的接口。而從類庫的層次上看,JMX 包括了核心類庫java.lang.managementjavax.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

                                    


                                                                                 JDK1.7

1.優化了對集合的支持,創建List / Set / Map 時寫法更簡單了。

List<String> list = ["item"];
String item 
= list[0];
Set
<String> set = {"item"};
Map
<String,Integer> map = {"key" : 1};
int value = map["key"];
 

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

try (BufferedReader br = new BufferedReader(new FileReader(path)) {
return br.readLine();
}

相對於以前版本,br不用代碼進行回收管理了,也就是省去了

finally {
br.close();
}
 
3.對泛型實力創建過程中類型應用進行了簡化,不用在重複指明泛型類型了
即這樣寫就行了:Map<String,String> hello = new Map<>();
 

4.可以在數字中使用下劃線了

int billion = 1_000_000_000;
 
5.對字符串進行switch case

例如:

String str="News";

switch (str)
  {
  case "News":

//....
    break;

//...

}

然而,這個功能在C#中早就支持了,java竟然這麼遲才更新。假若想在Java1.7以下版本怎樣實現switch case字符串的選擇呢。解決這一問題應該方法有很多,其中利用Java1.5的特性枚舉不愧爲最好的方法。

注意:在把字符串傳進Switch case之前,別忘了檢查字符串是否爲Null。(這個功能在C#中早就支持)

 

6.你可用作二進制字符前加上 0b 來創建一個二進制類型。

例如:

int binary = 0b1001_1001;


7.多重捕獲Multi-catch
catch(IOException | NullPointerException | ..........) {

}

8.運用List<String> tempList = new ArrayList<>();即泛型實例化類型自動推斷




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章