泛型
所謂泛型就是在定義類、接口、方法時使用類型形參,這個類型形參將在聲明變量、創建對象、調用方法時動態的指定。雖然在使用集合類,比如:List、Set等類時,會使用泛型,但是根據定義并不是只針對集合,在定義類的時候就可以指定泛型。
public class Person<T> {
private T info;
public Person(T info) {
this.info = info;
}
}
Person<String> person = new Person<>("name");
當創建了帶泛型聲明的接口、父類的時候,可以為該類接口創建實現類、或從該父類派生出子類。但需要注意的是,當使用這些泛型接口、父類的時候不能再包含類型形參。例如下面是一種錯誤的描述:
// 這是一種錯誤的描述
public class Student extend Person<T> {
}
可以使用如下的方式來繼承該類:
public class Student extend Person<String> {
}
或者不指定泛型類型,但是這樣會有警告信息:
public class Student extend Person {
}
有的時候我們在程序中需要使用泛型的父類,這個時候可以使用如下方式實現:
// 這種用法有警告信息
public void test(List list) {
....
}
這種方式是正確的,但是使用這種方式可能會引起警告信息,如果采用下面的方式來使用就會引起錯誤:
// 這種用法是錯誤的
public void test(List<Object> list) {
...
}
在Java中為了表示泛型類的父類,需要使用類型通配符,就是用?來表示。在上面的例子中可以使用如下的形式來表示:
// 這種表示方式表示所有List類的父類,沒有錯誤也沒有警告信息
public void test(List<?> list) {
...
}
但是這里存在一個問題,如果使用List<?>這種父類,在程序中使用的話還需要強制類型的轉換,轉換成需要的類型,例如:
public void test(List<?> list) {
for (Object obj : list) {
String str = (String)obj;
...
}
}
這種使用方式還需要把對象強制類型轉換一下,為了解決這種問題,可以給類型通配符設定一個上線:
public void test(List<? extends xxx> list) {
...
}
這種方式就可以把List中的對象當成xxx類型,直接訪問。
在定義泛型類的時候并不希望這個泛型類型是隨意添加的,需要指定該類型是某個類型的子類,這個時候需要指定泛型類型的上限。
為了解決這個問題需要指定類型形參的上限,例子如下:
public class Question<T extends Person> {
...
}
這個時候在使用類型T的時候就必須傳入Person的子類。
泛型方法
泛型方法的簽名如下:
修飾符 <T, S> 返回值類型 方法名(形參列表) {
...
}
T 和 S 都可以使用這種形式: T extends E,表示E是T的上限。
// 例子如下:
public <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o);
}
}
如果可以使用泛型方法,那泛型方法和類型通配符之間存在怎樣的區別:在大多數的情況下都可以使用泛型方法來代替類型通配符。通配符就是被設計用來支持靈活的子類化的,但是泛型方法就是允許類型形參被表示方法的一個或者多個參數之間的類型依賴關系,或者方法返回值與參數之間的類型依賴關系。