跳至內容

Java 5.0

本頁使用了標題或全文手工轉換
維基百科,自由的百科全書

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

新的特性[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)。

泛型(Generic Types)

[編輯]

泛型就像是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)

[編輯]

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的AspectJSpring也使用了大量的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.Scannerjava.util.Formatter類別被應用到輸入輸出中。另外,也出現了類似C語言printf()函數。

foreach迴圈

[編輯]

foreach迴圈,有時又稱forin迴圈,在許多程式語言(包括C#RubyJavaScript)中都有出現,可以直接將一個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 <= int2);  // 檢查兩者的值(触发了自动拆箱),     true
 System.out.println(int1 != int2);   // 檢查兩者的參考位置(没有触发自动拆箱),true!
 System.out.println(int1 == int2);  // 实际为檢查兩者的參考位置,false! 不能认为这是int值类型间的对比,此时还没有发生自动拆箱行为。

泛型擦除

[編輯]

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

註釋

[編輯]
  1. ^ New Features and Enhancements J2SE 5.0. [2013-05-14]. (原始內容存檔於2021-01-26).