1. 程式人生 > >JDK 1.5、1.6和1.7區別

JDK 1.5、1.6和1.7區別

JDK1.5(JDK5.0)

Java2標準版(Java2 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.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

jdk1.7的新特性:

1,switch中可以使用字串


Java程式碼 
  1. String s = "test";
  2. switch(s) {
  3. case"test" :
  4. System.out.println("test");
  5. case"test1" :
  6. System.out.println("test1");
  7. break;
  8. default:
  9. System.out.println("break");
  10. break;
  11. }

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



2,"<>"這個玩意兒的運用List<String> tempList = new ArrayList<>(); 即泛型例項化型別自動推斷。

3. 語法上支援集合,而不一定是陣列


Java程式碼 
  1. finalList<Integer> piDigits = [ 1,2,3,4,5,8 ];

final List<Integer> piDigits = [ 1,2,3,4,5,8 ];



4. 新增一些取環境資訊的工具方法


Java程式碼 
  1. File System.getJavaIoTempDir() // IO臨時資料夾
  2. File System.getJavaHomeDir() // JRE的安裝目錄
  3. File System.getUserHomeDir() // 當前使用者目錄
  4. File System.getUserDir() // 啟動java程序時所在的目錄
  5. .......

File System.getJavaIoTempDir() // IO臨時資料夾File System.getJavaHomeDir() // JRE的安裝目錄File System.getUserHomeDir() // 當前使用者目錄File System.getUserDir() // 啟動java程序時所在的目錄.......



5. Boolean型別反轉,空指標安全,參與位運算


Java程式碼 
  1. Boolean Booleans.negate(Boolean booleanObj)
  2. True => False , False => True, Null => Null
  3. booleanBooleans.and(boolean[] array)
  4. booleanBooleans.or(boolean[] array)
  5. booleanBooleans.xor(boolean[] array)
  6. booleanBooleans.and(Boolean[] array)
  7. booleanBooleans.or(Boolean[] array)
  8. booleanBooleans.xor(Boolean[] array)

Boolean Booleans.negate(Boolean booleanObj)True => False , False => True, Null => Nullboolean 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)



6. 兩個char間的equals


Java程式碼 
  1. booleanCharacter.equalsIgnoreCase(charch1,charch2)

boolean Character.equalsIgnoreCase(char ch1, char ch2)



7,安全的加減乘除


Java程式碼 
  1. intMath.safeToInt(longvalue)
  2. intMath.safeNegate(intvalue)
  3. longMath.safeSubtract(longvalue1,intvalue2)
  4. longMath.safeSubtract(longvalue1,longvalue2)
  5. intMath.safeMultiply(intvalue1,intvalue2)
  6. longMath.safeMultiply(longvalue1,intvalue2)
  7. longMath.safeMultiply(longvalue1,longvalue2)
  8. longMath.safeNegate(longvalue)
  9. intMath.safeAdd(intvalue1,intvalue2)
  10. longMath.safeAdd(longvalue1,intvalue2)
  11. longMath.safeAdd(longvalue1,longvalue2)
  12. intMath.safeSubtract(intvalue1,intvalue2)