每日学习:2011.3.4 Java泛型

1、在泛型代码内部,无法获取任何有关泛型参数类型的信息,Java泛型是使用擦除来实现的,这意味着当你在使用泛型时,任何具体的类型信息都被擦除了。
  所以需要为泛型指定边界(extends)=》泛型类型参数将擦除到它的第一个边界,当具有多重边界时,扩展基类只能有一个,而且必须放在第一位,接口可以有多个,用&来连接。

2、擦除的核心动机是它使得泛化的客户端可以用非泛化的类库来使用(迁移兼容性),泛型的目标是将类型安全检查移入编译期,避免运行时类型转化带来的不安全

3、擦除的补偿:引入类型标签,使用动态的isInstance()来判断类型,通过Class<T>.newInstance()来恢复

4、创建泛型数组的唯一方式是创建一个被擦除类型的新数组,然后对其转型=>(T[])new Object[size]
   因为有了擦除,数组的运行时类型就只能是Object[]
   数组对象在底层有详细实现,保证可以保留有关它们包含的对象类型的规则,而泛型不可以(数组支持协变)

5、关于容器的泛型:在这里其实我们讨论的是容器的类型,而不是容器持有的类型。与数组不同,泛型没有内建的协变类型,因为数组在语言中是完全定义的,因此可以内建编译期和运行时的检查。但在用泛型时编译器和运行时系统都不知道你想用类型做些什么,以及应该采用什么样的规则。

6、通配符(?):
List<? extends Fruit> fList = new ArrayList<Apple>();
//compile error:can't add any type of object
//fList.add(new Apple());
//fList.add(new Fruit());
//fList.add(new Object());
Fruit f = fList.get(0); //ok

上述代码解释: (? extends Fruit) 告诉编译器类型为一切扩展自Fruit的类型,知道这一边界后,Fruit返回类型的get是ok的,但List的add()的参数也是(? extends Fruit),这意味着可以是任何事物,而编译器无法验证"任何事物"的类型安全性。

List<? extends Fruit> 你可以将其读作“具有任何从Fruit继承的类型的列表”,但是实际上并不意味着这个List将持有任何类型的Fruit。通配符引用的是具体类型,因此它意味着“没有指定具体类型的List”;

你可能感兴趣的:(java)