1、自定义范型结构:范型类、范型接口、范型方法
范型类、范型接口在实例化时,如果没有指明范型,将被擦除,认为此范型类型为Object
泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如: <E1,E2,E3>
泛型类的构造器如下:public GenericClass(){}。
泛型的指定中不能使用基本数据类型,可以使用包装类替换。
在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。
不能使用new E[]。但是可以:E[] elements = (E[])new Object[capacity];
异常类不能是泛型的
父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
子类不保留父类的泛型:按需实现
没有类型 擦除
具体类型
子类保留父类的泛型:泛型子类
全部保留
部分保留
结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自己的泛型
2、范型方法
泛型方法的格式:
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
不是说在方法中使用了范型就是范型方法,
范型方法:在方法中出现了范型的结构,范型参数与类的范型参数没有关系,与范型方法所属的类是不是范型类都没有关系。
3、范型与继承
如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G<B>并不是G<A>的子类型。
4、通配符的使用
使用类型通配符:?。
List<?>是List<String>、List<Object>等各种泛型List的父类。
写入list中的元素时,不行。因为我们不知道list的元素类型,我们不能向其中 添加对象。
--------唯一的例外是null,它是所有类型的成员。
读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。
注意:
注意点1:编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用?
注意点2:编译错误:不能用在泛型类的声明上
注意点3:编译错误:不能用在创建对象上,右边属于创建集合对象
5、有限制的通配符
<?>
允许所有泛型的引用调用
通配符指定上限
上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
通配符指定下限
下限super:使用时指定的类型不能小于操作的类,即>=
举例:
<? extends Number> (无穷小 , Number]
只允许泛型为Number及Number子类的引用调用
<? super Number> [Number , 无穷大)
只允许泛型为Number及Number父类的引用调用
<? extends Comparable>
只允许泛型为实现Comparable接口的实现类的引用调用