Java 5.0

Java 從 5.0 版本開始，加入許多新特性，是 Java 歷史中修改最大的版本，許多特點模仿自 C#，因而被認為是為了與 C# 對抗。

新的特性

1.1 自動裝箱／拆箱（Auto-Boxing/Unboxing）

將 Java 中 8 個基本型別實現自動物件化和值化轉換，透過編譯器自動完成相關轉換程式碼的生成。

沒有自動裝箱／拆箱：

int int1 = 1;

Integer integer2 = new Integer (int1);

int int3 = integer2.intValue ;

有自動裝箱／拆箱：

int int1 = 1;

Integer integer2 = int1; // 自動裝箱

int int3 = integer2; // 自動拆箱

實際上將相關位元組碼反編譯後，會還原出其隱式呼叫的轉換方法：

int int1 = 1;

Integer integer2 = Integer.valueOf (int1); // 自動裝箱的本質，透過呼叫 valueOf 將值物件化

int int3 = integer2.intValue ; // 自動拆箱的本質，透過呼叫 xxxValue 將物件值化

自動裝箱的新功能，可能是從 C# 語言身上學習來的，Java 已經越來越像 C#。然而 Java 對自動裝箱／拆箱的支援，僅是利用編譯器實現，在 Java Bytecode 中，並無自動裝箱／拆箱的操作碼（opcode）。

1.2 泛型（Generic Types）

泛型就像是 C++ 的模板。原有的 Collection API 加上泛型支援後，增加對型別的檢查，減少程式錯誤的機會。

沒有泛型：

HashMap hm = new HashMap ;

int i=1;

String tt="test";

hm.put (new Integer (i), tt);

使用 Generic：

HashMap hm = new HashMap ;

int i=1;

String tt = "test";

hm.put (i, tt); // 在這裡對 int 自動裝箱成 Integer，也使用了引數的型別檢查

1.3 註解（Annotation）

Annotation 全名是 Program Annotation Facility，是 Java SE 5.0 的新功能。Java 的 Annotation 類似於.NET 的屬性（Attribute）。Java 的註解是一種介面（interface），繼承自 java.lang.annotation.Annotation。Class File 則貼上 ACC_ANNOTATION 標籤。

從 5.0 開始，javadoc 的 @deprecated（代表不建議使用的方法或類別）也被 Annotation 中的 @Deprecated 取代；另外，使用 Java 實作 SOP 的 AspectJ 與 Spring 也使用了大量的 Annotation。

// JDK 1.4

/ @todo to be implemented
/

void gimmeSomeLoving {throw new Exception ("not implemented");

}

// JDK 1.5

@todo

void gimmeSomeLoving {throw new Exception ("not implemented");

}

1.4 列舉型別（enum）

列舉型別也是 J2SE 5.0 的新功能。過去 Java 認為 enum 的關鍵字是不必要的功能，因為用 public static int field 就可以取代 enum，因此過去一直不用。J2SE 5.0 中的 class 如果是 enum，在 class file 中會被貼上一個 ACC_ENUM 標籤。

Enum 一般用來表示一組相同型別的常量。如性別、日期、月份、顏色等。對這些屬性用常量的好處是顯而易見的，不僅可以保證單例，且比較時候可以用 “==” 來替換 equals 。是一種好的習慣。 JDK1.5 之前沒有 Enum 這個型別，那時候一般用介面常量來替代。Java 有了 Enum 之後，可以更貼近的表示這種常量。

// JDK 1.4

class JavaTech {

public static final int J2ME = 1;

public static final int J2SE = 2;

public static final int J2EE = 3;

}

// JDK 1.5

public enum NewJavaTech {J2ME, J2SE, J2EE}

1.5 國際化

Java 語言嚴格區分位元組和字元。字元的儲存格式為 UCS-2，也就是隻能使用位於基本多文種平面的字元，從 Java 5 開始支援 UTF-16 字元。

另外，從 5.0 開始 Java 的程式也開始可以使用 Unicode 字元進行命名。

下面就是一個合法的 Java 程式，裡麵包含了中文字元作為字串的名稱，這個程式可以在編譯器中透過編譯。

public class HelloWorld {private String 文字 = "HelloWorld";}

1.6 輸入輸出

在 jdk1.5 及其以後版本中，java.util.Scanner 和 java.util.Formatter 類別被應用到輸入輸出中。另外，也出現了類似 C 語言的 printf 函式。

1.7 foreach 迴圈

foreach 迴圈，有時又稱 forin 迴圈，在許多程式語言（包括 C#、Ruby、JavaScript）中都有出現，可以直接將一個 Array 或 Map 展開，而不必由程式設計師自行檢查邊界，可以有效減少錯誤的機會。

int array1 = {1, 3, 5};

for (int i : array1){ //foreach 迴圈

System.out.println ("Number:"+i);

}

1.8 可變長度的引數

長久以來一直有使用者要求加入 printf 函式，受限於 Java 函式必須要有固定引數的限制，始終無法實現，在加入這個功能之後，連帶 printf 也變為可能。

1.9 static 引入

這個特性允許程式設計師將一個類別中的靜態內容引入到程式中。

static import java.lang.System.*;

public class HelloWorld {public static void main (String args){out.println ("Hello World.");

}

}

批評

Java 5.0 雖然加入許多的新特性，但為了與舊版本相容，JVM 並沒有隨之改變，而僅只是從編譯器動手腳，因而引發許多問題。討論 Java 語言問題的專書《Java Puzzle》就有專門的篇幅討論 5.0 之後造成的問題。

2.1 自動裝箱／拆箱的矛盾

自動裝箱這功能也造成了一些矛盾，例如：

Integer int1 = new Integer (1);

Integer int2 = new Integer (1);

System.out.println (int1>= int2); // 檢查兩者的值（觸發了自動拆箱）， true

System.out.println (int1

2.2 泛型擦除

和 C#，C++ 的泛型不同，Java 的泛型只用在型別檢查，使用的時候還要再做一次轉型和型別檢查。泛型資訊在編譯時會從程式碼中抹除（只保留作為元資料給反射功能獲得），泛型對應的值型別在位元組碼中為 java.lang.Object 型別，這是為了降低 JVM 的修改難度和保證老舊程式碼的執行相容。