Java 5.0

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

**新的特性**

**自動裝箱／拆箱（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）。

**泛型（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，也使用了參數的型別檢查

**註解（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");
}

**枚舉類型（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
}

**國際化**
Java語言嚴格區分字節和字符。字符的存儲格式為UCS-2，也就是隻能使用位於基本多文種平面的字元，從Java 5開始支持UTF-16字符。
另外，從5.0開始Java的程式也開始可以使用Unicode字元進行命名。
下面就是一個合法的Java程式，裡麵包含了中文字符作為字串的名稱，這個程式可以在編譯器中通過編譯。
public class HelloWorld {
private String文本 = "HelloWorld";
}

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

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

for(int i : array1){ // foreach迴圈
System.out.println("Number: "+i);
}

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

**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之後造成的問題。

**自動裝箱／拆箱的矛盾**
自動裝箱這功能也造成了一些矛盾，例如：
Integer int1 = new Integer(1);
Integer int2 = new Integer(1);

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

**泛型擦除**
和C#，C++的泛型不同，Java的泛型只用在型別檢查，使用的時候還要再做一次轉型和類型檢查。泛型信息在編譯時會從代碼中抹除（只保留作為元數據給反射功能獲得），泛型對應的值類型在字節碼中為java.lang.Object類型，這是為了降低JVM的修改難度和保證老舊代碼的運行兼容。

**註釋 ==