- 泛型類: 具有一個或多個類型變量的類,稱之為泛型類
class A<T> {}
-
在創建泛型類實例時,需要為其類型變量賦值 A<String> a = new A<String>();
- 如果創建實例時,不給類型變量賦值,那麼會有一個警告
-
泛型方法: 具有一個或多個類型變量的方法,稱之為泛型方法
class A<T> { public T fun(T t1) {} }
fun() 方法不是泛型方法,他是泛型類中的一個方法 public <T> fun(T t1) {} -> 他是泛型方法
- 泛型方法與泛型類沒甚麼關係,泛型方法不一定非要在泛型類中。
-
泛型在類中或方法中使用
- 泛型類中使用泛型
- 成員類型
- 返回值和參數類型
- 局部變量的引用上
- 泛型類中使用泛型
class A<T> {
private T bean; //泛型可在成員變量上使用
public T fun(T t) {} //泛型還可以在局部變量的引用類型上使用
public void fun2() { //泛型還可以在局部變量的引用類型上使用
T b = ...
new T(); //不行!
}
}
-
泛型的繼承和實現
class A<T> {} class AA extends A<String> {} //不是泛型類,父類是
- 繼承泛型類
- 子類不是泛型類: 需要給父類傳遞類型常量
- 當給父類傳遞的類型常量為 String 時,那麼在父類中所有 T 都會被 String 替換
- 子類是泛型類: 可以給父類傳遞類型常量,也可以傳遞類型變量
- 子類不是泛型類: 需要給父類傳遞類型常量
class AA1<T> extends A<T> {} class AA3<E> extends A<E> {}
- 繼承泛型類
package generic.test.demo;
import org.junit.Test;
public class Demo1 {
@Test
public void fun1() {
AA3<Long> aa3 = new AA3<Long>();
}
}
class A<T> {
private T t;
public T fun1() {
return t;
}
public void fun2(T t) {
this.t = t;
}
}
class AA1 extends A<Integer> {
}
class AA2 extends A<String> {
}
class AA3<E> extends A<E> {
}
-
通配符使用的場景: 方法的形參
-
通配符的優點: 使方法更加通用
-
通配符的分類: 無界通配: ? 子類限定: ? extends Object 父類限定: ? super Integer
-
通配符卻點 使變量使用上不再方便 無界: 參數和返回值為泛型的方法,不能使用 子類: 參數為泛型的方法不能使用 父類: 返回值為泛型的方法不能使用
-
比較通配符 boolean addAll(Collection<E> c)
List<Number> numList = new ArrayList<Number>(); List<Integer> intList = new ArrayList<Integer>(); numList.addAll(intList); //addAll(Collection<? extends Number> c), 傳遞的是 List<Integer>
package generic.test.demo;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class Demo2 {
@Test
public void fun1() {
Object[] objs = new Object[10];
List list = new ArrayList();
String[] strs = new String[10];
List<String> strList = new ArrayList<String>();
Object[] objArray = new String[10];
objArray[0] = new Integer(100); //ArrayStoreException
// List<Object> objList = new ArrayList<String>();\
/*
* 泛型引用和創建兩端,給出的泛型變量必須相同
*/
}
public void fun2() {
List<Integer> integerList = new ArrayList<Integer>();
print(integerList);
List<String> stringList = new ArrayList<String>();
print(stringList);
}
/*
* 其中的 ? 就是通配符
* 通配符只能出現在左邊,即不能在 new 時使用通配符
*/
/*
* ? 表示一個不確定的類型,他的值會在調用時確定下來
*/
public void print(List<? extends Object> list) {
/*
* 當使用通配符時,對泛型類中的參數為泛型的方法起到了副作用,不能再使用
*/
// list.add("hello");
/*
* 當使用通配符時,泛型類中返回值為泛型的方法也作廢了
*/
Object s = list.get(0);
/*
* 通配符好處,可以使泛型類型更加通用,尤其是在方法調用時形參使用通配符
*/
}
@Test
public void fun3() {
List<Integer> intList = new ArrayList<Integer>();
print1(intList);
List<Long> longList = new ArrayList<Long>();
print1(intList);
}
/*
* 給通配符添加了限定
* 只能傳遞 Number 或其子類型
* 子類通配對通用性產生了影響,但使用了形參更加靈活
*/
public void print1(List<? extends Number> list) {
// list.add(new Integer(100));
/*
* 返回值為泛型的方法
*/
Number number = list.get(0);
}
@Test
public void fun4() {
List<Integer> intList = new ArrayList<Integer>();
print2(intList);
List<Number> numList = new ArrayList<Number>();
print2(numList);
List<Object> objList = new ArrayList<Object>();
print2(objList);
}
/*
* 給通配符添加了限定
* 只能傳遞Integer類型,或其父類型
*/
public void print2(List<? super Integer> list) {
/*
* 參數為泛型的方法可以使用
*/
list.add(new Integer(100));
/*
* 返回值為泛型的方法,還是不能使用
*/
Object obj = list.get(0);
}
}