Java 5.0

Java從5.0版本開始，加入許多新特性，是Java歷史中修改最大的版本，許多特點模仿自C#，因而被認為是為了與C#對抗。 将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）。 泛型就像是C++的模板。原有的Collection API加上泛型支援後，增加對型別的檢查，減少程式錯誤的機會。 沒有泛型： HashMap hm = new HashMap(); int i=1; String tt="test"; hm.put(new Integer(i), tt); 使用Generic： HashMap <Integer, String>hm = new HashMap<Integer, String>(); int i=1; String tt = "test"; hm.put(i, tt); // 在這裏對int自動裝箱成Integer，也使用了參數的型別檢查 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"); } 枚举类型也是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迴圈，有時又稱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 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 <= int2); // 檢查兩者的值（触发了自动拆箱）， true System.out.println(int1 != int2); // 檢查兩者的參考位置（没有触发自动拆箱），true！ System.out.println(int1 == int2); // 实际为檢查兩者的參考位置，false！ 不能认为这是int值类型间的对比，此时还没有发生自动拆箱行为。 和C#，C++的泛型不同，Java的泛型只用在型別檢查，使用的時候還要再做一次轉型和类型检查。泛型信息在编译时会从代码中抹除（只保留作为元数据给反射功能获得），泛型对应的值类型在字节码中为java.lang.Object类型，这是为了降低JVM的修改难度和保证老旧代码的运行兼容。 New Features and Enhancements J2SE 5.0. [2013-05-14]. （原始内容存档于2021-01-26）.