Chapter11 泛型
11.1 泛型概述
- jdk 5.0新增的特性
- 在集合中使用泛型:
- 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
- 在实例化集合类时,可以指明具体的泛型类型
- 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位,都指定为实例化的泛型类型。
比如:add(E e)
—>实例化以后:add(Integer e)
- 注意点:
- 泛型的声明
interface List<T> 和 class GenTest<K,V>
- 其中, T,K,V不代表值,而是表示类型。 这里使用任意字母都可以。
- 常用T表示,是Type的缩写。
- 泛型的实例化:
- 一定要在类名后面指定类型参数的值(类型)。如:
List<String> strList = new ArrayList<String>(); Iterator<Customer> iterator = customers.iterator();
- T只能是类,不能用基本数据类型填充,但可以使用包装类填充。
- 把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想
- 一定要在类名后面指定类型参数的值(类型)。如:
- 注意事项
- 泛型不同的引用不能相互赋值
- 异常类不能声明为泛型类
- 不能使用
new E[]
。但是可以:E[] elements = (E[])new Object[capacity]
; - 静态方法中不能使用类的泛型
- 父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
- 子类不保留父类的泛型:按需实现
- 没有类型 擦除
- 具体类型
- 子类保留父类的泛型:泛型子类
- 全部保留
- 部分保留
- 结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自己的泛型
class Father<T1, T2> { } // 子类不保留父类的泛型 // 1)没有类型 擦除 class Son1 extends Father {// 等价于class Son extends Father<Object,Object>{ } // 2)具体类型 class Son2 extends Father<Integer, String> { } // 子类保留父类的泛型 // 1)全部保留 class Son3<T1, T2> extends Father<T1, T2> { } // 2)部分保留 class Son4<T2> extends Father<Integer, T2> { }
2. 泛型方法
- 子类不保留父类的泛型:按需实现
- 格式
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常 public <E> List<E> Order(E[] arr) { // }
- 泛型方法可以声明为静态的。原因:泛型参数是在调用方法时确定的。并非在实例化类时确定。
11.3 泛型在继承上的体现
- 类A是类B的父类,但是G<A> 和G<B>二者不具备子父类关系,二者是并列关系。
- 类A是类B的父类,A<G> 是 B<G> 的父类
List<Object> list1 = null; List<String> list2 = new ArrayList<String>(); //此时的list1和list2的类型不具有子父类关系 list1 = list2;//编译不通过
AbstractList<String> list1 = null; List<String> list2 = null; ArrayList<String> list3 = null; list1 = list3;//编译通过 list2 = list3;//编译通过
11.4 通配符的使用
通配符?
类A是类B的父类,G<A>和G<B>是没有关系的,二者共同的父类是:G<?>List<Object> list1 = null; List<String> list2 = null; List<?> list = null; list = list1; list = list2;
添加(写入):
对于List<?>
就不能向其内部添加数据,除了添加null之外。获取(读取):
允许读取数据,读取的数据类型为Object
。List<?> list = null Object o = list.get(0); System.out.println(o);
有限制的通配符
<?>
:允许所有泛型的引用调用- 通配符指定上限
- 上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
- 通配符指定下限
- 下限super:使用时指定的类型不能小于操作的类,即>=
- 举例:
<? extends Number>
(无穷小 , Number]
只允许泛型为Number及Number子类的引用调用<? super Number>
[Number , 无穷大)
只允许泛型为Number及Number父类的引用调用<? extends Comparable>
只允许泛型为实现Comparable接口的实现类的引用调用
- 代码示例:
List<? extends Person> list1 = null; List<? super Person> list2 = null; List<Student> list3 = new ArrayList<Student>(); List<Person> list4 = new ArrayList<Person>(); List<Object> list5 = new ArrayList<Object>(); list1 = list3; list1 = list4; list2 = list4; list2 = list5; //读取数据: list1 = list3; Person p = list1.get(0); Student s = list1.get(0); //编译不通过 list2 = list4; Object obj = list2.get(0); Student s = list1.get(0); //编译不通过 //写入数据: list1.add(new Student());//编译不通过 //编译通过 list2.add(new Person()); list2.add(new Student());