iT邦幫忙

DAY 16
3

實戰 Java SE 7 系列 第 16

復習 - 泛型(Generic)

在講下一個新的功能之前,我們先來復習一下什麼是泛型(Generic)。
在 Java SE 1.5 版之前,還沒有納入泛型的語法,沒有泛型有什麼壞處呢?我們拿最常用的 Collection 類別來看看:

package idv.jacky.ironman4.day16;

import java.util.ArrayList;
import java.util.List;

public class Day16Example1 {

	public static void main(String[] args) {
		List fruits = new ArrayList();
		fruits.add(new Apple());
		fruits.add(new Banana());
		fruits.add(new Apple());
		
		makeJuice(fruits);
	}
	
	public static void makeJuice(List fruits) {
		for(Object obj : fruits) {
			Apple a = (Apple)obj;
			a.makeJuice();
		}
	}

}

上面的程式碼裡,我們宣告了一個 fruits 的 List 物件(用ArrayList 為實體),然後依序放入了 Apple,Banana 和 Apple 這三個物件。Apple 和 Banana 的程式碼如下:

package idv.jacky.ironman4.day16;

public class Apple {

	public void makeJuice() {
	}
}





package idv.jacky.ironman4.day16;

public class Banana {

}

Apple 跟 Banana 兩個類別最大的不同在於,Apple 類別裡有個 makeJuice 的方法,而 Banana 類別裡沒有(應該沒有人打香蕉汁來喝吧??)。回到最上面的程式碼,有個叫 makeJuice 的方法,所傳入的參數是個 List 物件;在方法裡我們會把 List 物件裡的物件一個個拿出來,轉成 Apple 物件後呼叫物件自己的 makeJuice 方法。

整個程式可以正常的編譯,但在執行時就出了問題了,錯誤訊息是
Exception in thread "main" java.lang.ClassCastException: idv.jacky.ironman4.day16.Banana cannot be cast to idv.jacky.ironman4.day16.Apple
at idv.jacky.ironman4.day16.Day16Example1.makeJuice(Day16Example1.java:19)
at idv.jacky.ironman4.day16.Day16Example1.main(Day16Example1.java:14)

是的,當程式試著將一個 Banana 物件 強迫轉型成 Apple 物件時,JVM 就會丟出 ClassCaseExcetpion!因為香蕉不可能變成蘋果!

Java 是一種 強型別程式語言(Stong Typing Programming Language),簡單的說就是,Java 程式碼在編譯時期,就會檢查各個宣告的變數,是否已指定了正確的型態。不過像這個例子,Java 編譯器確束手無策,我們明明知道,程式第19行有潛在的危險,但確還是讓程式碼能成功編譯。一直到執行時期,才丟出例外,但為時已晚。

基於這類的原因,Java SE 1.5 版終於在大家的期盼下加入了泛型這個功能!於是我們改造了一下這個範例

package idv.jacky.ironman4.day16;

import java.util.ArrayList;
import java.util.List;

public class Day16Example2 {

	public static void main(String[] args) {
		List<Apple> fruits = new ArrayList<Apple>();
		fruits.add(new Apple());
		fruits.add(new Banana());
		fruits.add(new Apple());
		
		makeJuice(fruits);
	}
	
	public static void makeJuice(List<Apple> fruits) {
		for(Apple a : fruits) {
			a.makeJuice();
		}
	}

}

泛型的使用方式很簡單,就是在 Collection 類別後加上角刮號(大於、小於),然後把型別指定進去。以程式第9行來說,就是宣告一個只能放 Apple 物件的 List 物件。既然宣告只能放 Apple 物件,那原本的第11行在這裡就會出錯,程式會沒辦法成功地編譯,編譯時會告訴你錯誤和原因:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method add(Apple) in the type List<Apple> is not applicable for the arguments (Banana)
at idv.jacky.ironman4.day16.Day16Example2.main(Day16Example2.java:11)

這樣一來,我們在寫程式的過程式,就會修正這個錯誤,而剛剛執行時期的錯誤也就不會發生,讓程式能更穩定的執行!

這是泛型的第一種基本應用 - 限制,限制你不能將不同的型別,指定給某種類別,例如 Collection。


上一篇
Project Coin - More Precise Rethrow
下一篇
復習 - 泛型(Generic) 完
系列文
實戰 Java SE 7 31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言