久草最新视频-久草最新网址-久国产-久国产视频-天天插夜夜操-天天插一插

北京北大青鳥學校學術部講解:Java類庫中的泛型(一)

北京北大青鳥學校學術部講師將繼續講解關于Java泛型的技術知識,關于Java泛型的定義、相關例子等請參考之前的幾篇文章,在這里就不做陳述了。今天這篇文章,將主講介紹一下Java類庫中的泛型(北大青鳥課程

集合類
北京北大青鳥學校專家介紹:到目前為止,Java 類庫中泛型支持存在最多的地方就是集合框架。就像容器類是 C++ 語言中模板的主要動機一樣(參閱 附錄 A:與 C++ 模板的比較)(盡管它們隨后用于很多別的用途),改善集合類的類型安全是 Java 語言中泛型的主要動機。集合類也充當如何使用泛型的模型,因為它們演示了泛型的幾乎所有的標準技巧和方言。(北大青鳥課程

所有的標準集合接口都是泛型化的 —— Collection、List、Set 和 Map。類似地,集合接口的實現都是用相同類型參數泛型化的,所以 HashMap 實現 Map 等。

集合類也使用泛型的許多“技巧”和方言,比如上限通配符和下限通配符。例如,在接口 Collection 中,addAll 方法是像下面這樣定義的:
interface Collection {
boolean addAll(Collection);
}

該定義組合了通配符類型參數和有限制類型參數,允許您將 Collection 的內容添加到 Collection。(北大青鳥課程

北京北大青鳥學校專家提醒:如果類庫將 addAll() 定義為接受 Collection,您就不能將 Collection 的內容添加到 Collection。不是限制 addAll() 的參數是一個與您將要添加到的集合包含相同類型的集合,而有可能建立一個更合理的約束,即傳遞給 addAll() 的集合的元素 適合于添加到您的集合。有限制類型允許您這樣做,并且使用有限制通配符使您不需要使用另一個不會用在其他任何地方的占位符名稱。

應該可以將 addAll() 的類型參數定義為 Collection。但是,北京北大青鳥學校專家認為,這不但沒什么用,而且還會改變 Collection 接口的語義,因為泛型版本的語義將會不同于非泛型版本的語義。這闡述了泛型化一個現有的類要比定義一個新的泛型類難得多,因為您必須注意不要更改類的語義或者破壞現有的非泛型代碼。

作為泛型化一個類(如果不小心的話)如何會更改其語義的一個更加微妙的例子,注意 Collection.removeAll() 的參數的類型是 Collection,而不是 Collection。這是因為傳遞混合類型的集合給 removeAll() 是可接受的,并且更加限制地定義 removeAll 將會更改方法的語義和有用性。(北大青鳥課程
 
其他容器類
北京北大青鳥學校專家介紹:除了集合類之外,Java 類庫中還有幾個其他的類也充當值的容器。這些類包括 WeakReference、SoftReference 和 ThreadLocal。它們都已經在其包含的值的類型上泛型化了,所以 WeakReference 是對 T 類型的對象的弱引用,ThreadLocal 則是到 T 類型的線程局部變量的句柄。

泛型不止用于容器
泛型最常見最直觀的使用是容器類,比如集合類或引用類(比如 WeakReference)。Collection 中類型參數的含義很明顯 —— “一個所有值都是 V 類型的集合”。類似地,ThreadLocal 也有一個明顯的解釋 —— “一個其類型是 T 的線程局部變量”。但是,泛型規格說明中沒有指定容積。(北大青鳥課程

像 Comparable 或 Class 這樣的類中類型參數的含義更加微妙。有時,就像 Class 中一樣,類型變量主要是幫助編譯器進行類型推理。有時,就像隱含的 Enum> 中一樣,類型變量只是在類層次結構上加一個約束。

Comparable
Comparable 接口已經泛型化了,所以實現 Comparable 的對象聲明它可以與什么類型進行比較。北京北大青鳥學校專家總結:(通常,這是對象本身的類型,但是有時也可能是父類。)
public interface Comparable {
public boolean compareTo(T other);
}

所以 Comparable 接口包含一個類型參數 T,該參數是一個實現 Comparable 的類可以與之比較的對象的類型。這意味著如果定義一個實現 Comparable 的類,比如 String,就必須不僅聲明類支持比較,還要聲明它可與什么比較(通常是與它本身比較):
public class String implements Comparable { ... }

現在來考慮一個二元 max() 方法的實現。您想要接受兩個相同類型的參數,二者都是 Comparable,并且相互之間是 Comparable。幸運的是,如果使用泛型方法和有限制類型參數的話,這相當直觀:
public static > T max(T t1, T t2) {
if (t1.compareTo(t2) > 0)
    return t1;
else
    return t2;
}

北京北大青鳥學校專家介紹:在本例中,您定義了一個泛型方法,在類型 T 上泛型化,您約束該類型擴展(實現) Comparable。兩個參數都必須是 T 類型,這表示它們是相同類型,支持比較,并且相互可比較。容易!

更好的是,編譯器將使用類型推理來確定當調用 max() 時 T 的值表示什么意思。所以根本不用指定 T,下面的調用就能工作:
String s = max("moo", "bark");

編譯器將計算出 T 的預定值是 String,因此它將進行編譯和類型檢查。但是如果您試圖用不實現 Comparable 的 類 X 的參數調用 max(),那么編譯器將不允許這樣做。
 
Class
類 Class 已經泛型化了,但是很多人一開始都感覺其泛型化的方式很混亂。Class 中類型參數 T 的含義是什么?事實證明它是所引用的類接口。怎么會是這樣的呢?那是一個循環推理?如果不是的話,為什么這樣定義它?

在以前的 JDK 中,Class.newInstance() 方法的定義返回 Object,您很可能要將該返回類型強制轉換為另一種類型:
class Class {
Object newInstance();
}
但是使用泛型,您定義 Class.newInstance() 方法具有一個更加特定的返回類型:
class Class {
T newInstance();
}(北大青鳥課程

如何創建一個 Class 類型的實例?北京北大青鳥學校專家介紹,就像使用非泛型代碼一樣,有兩種方式:調用方法 Class.forName() 或者使用類常量 X.class。Class.forName() 被定義為返回 Class。另一方面,類常量 X.class 被定義為具有類型 Class,所以 String.class 是 Class 類型的。

讓 Foo.class 是 Class 類型的有什么好處?北京北大青鳥學校專家解答:最大的好處是,通過類型推理的魔力,可以提高使用反射的代碼的類型安全。另外,還不需要將 Foo.class.newInstance() 強制類型轉換為 Foo。

考慮一個方法,它從數據庫檢索一組對象,并返回 JavaBeans 對象的一個集合。您通過反射來實例化和初始化創建的對象,但是這并不意味著類型安全必須完全被拋至腦后。考慮下面這個方法:
public static List getRecords(Class c, Selector s) {
// Use Selector to select rows
List list = new ArrayList();
for (/* iterate over results */) {
    T row = c.newInstance();
    // use reflection to set fields from result
    list.add(row);
}
return list;
}
北大青鳥課程
可以像下面這樣簡單地調用該方法:
List l = getRecords(FooRecord.class, fooSelector);
編譯器將會根據 FooRecord.class 是 Class 類型的這一事實,推斷 getRecords() 的返回類型。您使用類常量來構造新的實例并提供編譯器在類型檢查中要用到的類型信息。
 
用 Class 替換 T[]
Collection 接口包含一個方法,用于將集合的內容復制到一個調用者指定類型的數組中:
public Object[] toArray(Object[] prototypeArray) { ... }

toArray(Object[]) 的語義是,如果傳遞的數組足夠大,就會使用它來保存結果,否則,就會使用反射分配一個相同類型的新數組。一般來說,單獨傳遞一個數組作為參數來提供想要的返回類型是一個小技巧,但是在引入泛型之前,這是與方法交流類型信息最方便的方式。

有了泛型,就可以用一種更加直觀的方式來做這件事。不像上面這樣定義 toArray(),泛型 toArray() 可能看起來像下面這樣:
public T[] toArray(Class returnType)
調用這樣一個 toArray() 方法很簡單:
FooBar[] fba = something.toArray(FooBar.class);

Collection 接口還沒有改變為使用該技術,因為這會破壞許多現有的集合實現。但是如果使用泛型從新構建 Collection,則當然會使用該方言來指定它想要返回值是哪種類型。
 
Enum
JDK 5.0 中 Java 語言另一個增加的特性是枚舉。當您使用 enum 關鍵字聲明一個枚舉時,編譯器就會在內部為您生成一個類,用于擴展 Enum 并為枚舉的每個值聲明靜態實例。所以如果您說:
public enum Suit {HEART, DIAMOND, CLUB, SPADE};

編譯器就會在內部生成一個叫做 Suit 的類,該類擴展 java.lang.Enum 并具有叫做 HEART、DIAMOND、CLUB 和 SPADE 的常量(public static final)成員,每個成員都是 Suit 類。(北大青鳥課程)

與 Class 一樣,Enum 也是一個泛型類。但是與 Class 不同,它的簽名稍微更復雜一些:
class Enum> { . . . }
這究竟是什么意思?這難道不會導致無限遞歸?

我們逐步來分析。類型參數 E 用于 Enum 的各種方法中,比如 compareTo() 或 getDeclaringClass()。為了這些方法的類型安全,Enum 類必須在枚舉的類上泛型化。

所以 extends Enum 部分如何理解?

北京北大青鳥學校專家介紹,該部分又具有兩個部分。第一部分指出,作為 Enum 的類型參數的類本身必須是 Enum 的子類型,所以您不能聲明一個類 X 擴展 Enum。第二部分指出,任何擴展 Enum 的類必須傳遞它本身 作為類型參數。您不能聲明 X 擴展 Enum,即使 Y 擴展 Enum。

總之,Enum 是一個參數化的類型,只可以為它的子類型實例化,并且這些子類型然后將根據子類型來繼承方法。幸運的是,在 Enum 情況下,編譯器為您做這些工作,一切都很好。(北京北大青鳥學校,未完待續)
 

北大青鳥網上報名
北大青鳥招生簡章
主站蜘蛛池模板: 亚洲综合图色国模40p| 亚洲国产精品福利片在线观看| 欧美亚洲h在线一区二区| 人久热欧美在线观看量量| 性感美女毛片| 亚洲女同精品中文字幕| 亚洲 国产精品 日韩| 日本在线亚州精品视频在线| 日韩一区二区三区不卡| 奇米一区二区三区四区久久| 亚 洲 成 人 动 漫在线| 日韩一级黄色片| 日韩精品一区在线| 天天上天天操| 一级毛片aa| 亚洲综合视频在线观看| 亚洲一级毛片免费观看| 日韩精品视频免费观看| 欧美日韩午夜视频| 三a级毛片| 日韩精品成人免费观看| 午夜在线免费视频| 青草青青青| 亚洲国产成人精品区| 四虎免费视频| 亚洲人和日本人jzz护士 | 欧美色成人| 亚洲天堂网2014| 欧美综合色网| 天堂网中文字幕| 视频一区免费| 人人综合| 天天操中文字幕| 日韩一区二区三区四区不卡| 特级生活片| 亚洲欧洲在线视频| 亚洲第一中文字幕| 天天插天天射天天操| 欧美日韩中| 日本最新免费网站| 亚洲色图国产|