Java - 泛型與Object型態使用上的差異

一般我們若寫一個method,回傳的基本型態可能不是只有一種時,也許會將他訂為Object,

如此一來該method能符合回傳不同型態的資料。但是當您在呼叫端取得回傳的值時,將需

要透過轉型的方式來處理,如assign to 某個變數,而且也有可能無法確認轉型的使用與對應

的值是否相符,若不符將在執行時發生java.lang.ClassCastException。

若是定義一個泛型類別,當您使用該類別時,可以指定該類別泛型要帶入的型態,

如 XXClass<Integer> obj = new XXXClass<Integer>();

類別型態或自訂類別都OK,如此一來的好處是,當您在使用該類別的method時,若

該method本身帶入的參數定義的型態為泛型別(T),則帶入的值將與您一開始宣告的型別

相符,如上為Integer,否則在編譯時就會出錯!

接下來,將在這邊舉泛型與Object型態使用上的差異範例。

Object型態使用的類別如下:
class Container1{
 Object save[] = new Object[10];
 int index = 0;
 
 public void set(Object thing){
  this.save[index++] = thing;
 }
 
 public Object get(int i){
  if(this.save[i] != null)
   return this.save[i];
  else
   return null;
 }
}

如上,Container1內的相關回傳型別及帶入型別皆設定為Object型別

public static void main(String[] args) {
   Container1 c = new Container1();
   c.set("book");
   c.set(123);
   c.set("computer");

   int num = (int) c.get(1);
   System.out.println(num);
   String str1 = (String) c.get(1);
   System.out.println(str1);
}

在main做宣告使用Container1時,使用set method不管帶入String、int皆不會有問題。

但是在get時,assign進一個變數,需要做型別的轉換,如上:(String) c.get(1);將出錯

由於c.get(1);本身為Integer類的型態,因此會出現轉型的錯誤在執行後,而在編譯時並不會

出錯!

泛型宣告的類別如下:
class Container2<T>{
 List<T> save = new ArrayList<T>(10);
 int index = 0;
 
 public void set(T thing){
  this.save.add(thing);
 }
 
 public T get(int i){
  if(this.save.get(i) != null)
   return this.save.get(i);
  else
   return null;
 }
}

一樣在main method內宣告Container2做如同上面的操作

Container2<String> c1 = new Container2<String>();
c1.set("book");
//c1.set(123);
c1.set("computer");

String str2 = c1.get(1);
System.out.println(str2);

發現c1.set(123);將會出錯,由於一開始在做初始化指定的泛型別為String,因此在使用

set時只能帶入String型態的value,間接也幫我們先進行了型態的檢查,避免出錯!

留言