1、”泛型“这个术语的意思是:”适用于许多许多的类型“。
2、泛型。其中尖括号括起来的的是类型参数(可以由多个),它指定了这个容器实例可以保存的类型。(p217)
3、基本类型无法作为类型参数。
4、对于一个static的方法而言,无法访问泛型类的类型参数,所以,如果static方法需要使用泛型能力,就必须使其成为泛型方法。
5、当使用泛型类时,必须在创建对象的时候指定类型参数的值,而使用泛型方法的时候,通常不必指明参数类型,因为编译器会为我们找出具体的类型,这称为类型参数推断。
要定义一个泛型方法,只需将泛型参数列表置于返回值之前,如下:
//泛型方法
public <T> void f(T x) {
System.out.println(x.getClass().getName());
}
//泛型方法中出现的泛型必须在返回值前进行声明泛型类型,否则泛型方法中将无法使用该类型的泛型
public static <A, B, C, D> FourTuple<A, B, C, D> tuple(A a, B b, C c, D d)
return new FourTuple<A, B, C, D>(a, b, c, d);
}
//泛型类,泛型类只需要将泛型写在类名后即可
class GenericityClass <T> {
}
6、在泛型代码内部,无法获得任何有关泛型参数类型的信息。因此,你可以知道诸如类型参数标识符和泛型类型边界这边类的信息——你却无法知道用来创建某个特定实例的实际的类型参数。Java泛型是使用擦除来实现的,这意味着当你在使用泛型时,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象。因此List<String>和List<Integer>在运行时事实上是相同的类型。这两种形式都被擦除成它们的“原生类型”,即List。(p373)7、只有当你希望代码使用的类型参数比某个具体类型(以及它的所有子类型)更加“泛化”时——也就是说,当你希望代码能够跨多个类工作时,使用泛型才有所帮助。(p375)
8、泛型类型只有在静态类型检查期间才出现,在此之后,程序中的所有泛型类型都将被擦除,替换为它们的非泛型上界。例如,诸如List<T>这样的类型注解将被擦除为List,而普通的类型变量在未指定边界的情况下将被擦除为Object
9、因为擦除在方法体中移除了类型信息,所以在运行时的问题就是边界:即对象进入和离开方法的地方,这些正是编译器在编译期执行类型检查并插入转型代码的地点。(p378)
10、不能创建泛型数组,一般的解决方案是在任何想要创建泛型数组的地方都使用ArrayList。(p383)
List<T> array = new ArrayList<T>();
成功创建泛型数组的唯一方式就是创建一个被擦除类型的新数组,然后对其进行转型。
public class GenericArrayWithTypeToken<T> {
private T[] array;
@SuppressWarnings("unchecked")
public GenericArrayWithTypeToken(Class<T> type, int sz) {
array = (T[]) Array.newInstance(type, sz);
}
public void put(int index, T item) {
array[index] = item;
}
public T get(int index) {
return array[index];
}
// Expose the underlying representation:
public T[] rep() {
return array;
}
public static void main(String[] args) {
GenericArrayWithTypeToken<Integer> gai = new GenericArrayWithTypeToken<Integer>(Integer.class, 10);
// This now works:
Integer[] ia = gai.rep();
System.out.println(Arrays.toString(ia));
}
}
11、边界
因为擦除移除了类型信息,所以,可以用无界泛型参数调用的方法只是那些可以用Object调用的方法。但是如果能够将这个参数限制为某个类型子集,那么你就可以用这些类型子集来调用方法。为了执行这种限制,Java泛型重用了extends关键字。要理解extends关键字在泛型边界上下文环境中和普通情况下所具有的意义是完全不同的。
//Dog是Pet的一个子类
//<? extends Pet>这种写法,可以不用强制转换
public static Map<Person, List<? extends Pet>> petPeople = new HashMap<Person, List<? extends Pet>>();
petPeople.put(new Person(), Arrays.asList(new Dog()));
public static Map<Person, List<Pet>> petPeople = new HashMap<Person, List<Pet>>();
petPeople.put(new Person(), Arrays.asList(new Dog()));//编译通不过
petPeople.put(new Person(), Arrays.asList((Pet)new Dog()));//必须进行强制转换
3、学习泛型的几个问题:
(1)Java泛型的局限是什么?
(2)Java泛型的边界在哪里?