一、    泛型:

l   泛型目的就是要維護「型別」的安全性,讓建構集合(set)時的錯誤能在編譯期間就抓到,不會等執行時才發生錯誤。

l   例如使用ArrayList時,因為可以塞入不同的object進去,當我們取出來時都會是Object的型別,很容易造成混淆。

l   例如我們要呼叫dogeat(),但dogcatfish動作都不一樣,但從ArrayList中取出來都是objectobject根本不認識eat(),就算轉型,也會造成不知道該物件到底是dog or cat

l   透過泛型,可以限定裡面能存放的物件型別,若加入其他物件皆能馬上發現,不會到執行期間才發生問題。

Public class ArrayList<E> extends AbstracList<E> implements List<E>…{
        Public Boolean add(E o){…}
}

上面程式碼中的E是用來建構與初始ArrayList的型別,若我們宣告時使用ArrayList<String>,那String會取代所有宣告成E的位置。

Public <T extends Animal>void takeThing(ArrayList<T> list)
-------------------------------------------------------------------------------
Public void takeThing(ArrayList<Animal> list)

上面兩行的宣告方式意思不同,第一個T extends Animal代表說,這個T可以是extendsimplements AnimalsubClass,但是第二個代表傳入的只能是Animal

l   因此要讓ArrayList中的Object進行sort時,可使用Collections.sort來進行,但此methods的宣告是<T extends Comparable>void takeThing,因此ArrayList中的物件必需要extendsimplements Comparable才行。

l   除了讓該Class extendsimplements之外,也可以額外建立一個class專門做這個動作,當需要Collections的處理時,再一起把兩個class放進來即可,此方法較好管理。


 

二、    Set集合的關係

List:負責處理順序

Set:重視獨一無二,不允許資料重覆

Map:透過Key來找資料,資料可以重覆但Key不行

l   之前所採用的ArrayList就是List的一種,重視資料的順序,若要讓資料是獨一無二的話,必需採用Set來進行。

l   在用歌曲(song)為例,歌名不能夠重覆,可以改用HashSet來做。

l   但是物件的重覆,比對時是採用hashCode,因此若要用equals()來比對物件,必需Override hashCodeequals兩個methods

l   若兩個物件都是參考的同一個物件的話(指標指向同一物件),則hashcode計會相同。

Public boolean equals(Object song){
                Return getTitle().equals(song.getTitle());
}

l   以上方法就可以用equals來判斷兩個物件是否相同,但是一般來說,物件相同代表hashCode也要相同,只Override hashCode是不夠的(對於Set來說兩者皆要相同才可以)

Public int hashCode(){
                Return title.hashCode();
}

l   若想要set不重覆又要可排序,可以用TreeSet,他擁有自動排序之功能,但缺點在於不需排序時,用此set會影響效能。同理,TreeSet會自動排序,因此加進去的class必需要extendsimplements Comparable

三、    Map:

l   Map是依照key的方式來加入資料,key不可重覆,但指向的物件可以相同。

l   因為map需要一個Key,因此需要兩個型別參數<String, Integer>stringkeyint是值

HashMap<String, Integer> scores = new HashMap<String, Integer>();

l   因為map需要一個Key,因此需要兩個型別參數


 

四、    泛型與參數的問題

l   若我們用以下方法宣告,代表該AarrayList可以加入有extends Animalsubclass

ArrayList<Animal> animal = new ArrayList<Animal>();
Public void takeAnimal(ArrayList<Animal> animals){
        For(Animal a : animals)
}

l   依照多型概念,應該可以傳入ArrayList<dog>進去,但是在此會發生error

l   因為如果傳入ArrayList<dog>進去,對於function來說是ArrayList<Animal>,是可以在ArrayList<Animal>加入一個cat,但這就會產生問題,我們對ArrayList<dog>加入了一個cat物件,雖然可以通過編譯但執行會發生錯誤。

Public void takeAnimal(ArrayList<? extends Animal> animals){
        For(Animal a : animals)
}

l   用以上方法可以限定,function中的ArrayList不準加入任何物件

Public <T extends Animal>void takeThing(ArrayList<T> list)

等於

Public void takeAnimal(ArrayList<? extends Animal> animals)

l   至於?T是沒有什麼區別的,但如果function中有兩個參數皆是用同一個型別的話,用T的方式可以比較簡潔。

Public <T extends Animal>void takeThing(ArrayList<T> list,ArrayList<T> two)

 

文章標籤
全站熱搜
創作者介紹
創作者 y23462001 的頭像
y23462001

y23462001的部落格

y23462001 發表在 痞客邦 留言(0) 人氣(807)