集合接口或集合类在jdk5.0时都修改为带泛型的结构。
在实例化集合类时,可以指明具体的泛型类型;
泛型的类型必须是类,不能是基本数据类型,需要用到基本数据类型的位置,拿包装类替换;
如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型。
Map<String,Integer> map = new HashMap<>();
//Map<String,Integer> map = new HashMap<String,Integer>();与上式等价
Set<Map.Entry<String,Integer>> set = map.entrySet();
for (Map.Entry<String,Integer> o:set){
List<Integer> list = new ArrayList<Integer>();
2.2 自定义泛型类、泛型接口、泛型方法
(1)泛型的声明
interface List<T> 和class GenTest<K,V> 其中,T,K,V不代表值,而是表示类型。这里使用任意字母都可以。 常用T表示,是Type的缩写。
泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如: <E1,E2,E3>
(2)泛型的实例化
泛型类的构造器如下:public GenericClass(){}。 而下面是错误的:public GenericClass<E>(){}
一定要在类名后面指定类型参数的值(类型)。如: List<String> strList = new ArrayList<String>(); Iterator<Customer> iterator = customers.iterator();
T只能是类,不能用基本数据类型填充。但可以使用包装类填充
把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想
泛型如果不指定,将被
擦除
,泛型对应的类型均按照Object处理,但不等价 于Object。经验:泛型要使用一路都用。要不用,一路都不要用。
如果泛型结构是一个接口或抽象类,则不可创建泛型类的对象。
jdk1.7,泛型的简化操作:ArrayList<Fruit> flist = new ArrayList<>();
在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态 属性的类型、非静态方法的参数类型、非静态方法的返回值类型。
但在静态方法中不能使用类的泛型
。
异常类不能是泛型的
父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
子类不保留父类的泛型:按需实现
-
没有类型 擦除
-
子类保留父类的泛型:泛型子类
结论:
子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自 己的泛型
2.3 泛型与继承的关系
类A是类B的父类===》但G<A>和G<B>二者不具备子父类关系,二者是并列关系,二者共同的父类是:G<?>
类A是类B的父类===》B<G>是A<G>的子类
2.4 通配符
List<?>是List<String>、List<Object>等各种泛型List的父类。
以List<?>为例,能读取其中的数据,因为不管存储的是什么类型的元素,其一定是Object类的或其子类的。
以List<?>为例,不可以向其中写入数据,因为没有指明可以存放到其中的元素的类型,唯一例外的是:null
2.5 有限制的通配符
-
<?> 允许所有泛型的引用调用
-
通配符指定上限:不能往里存,只能往外取
-
上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
-
通配符指定下限:不影响往里存,但往外取只能放在Object对象里
-
下限super:使用时指定的类型不能小于操作的类,即>=
<? extends Number> (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用
<? super Number> [Number , 无穷大) 只允许泛型为Number及Number父类的引用调用
<? extends Comparable> 只允许泛型为实现Comparable接口的实现类的引用调用
PESC(Producer Extends Consumer Super)原则:
-
Producer Extends 生产者使用Extends来确定上界,往里面放东西来生产
-
Consumer Super 消费者使用Super来确定下界,往外取东西来消费
频繁往外读取内容的,适合用上界Extends,即extends 可用于的返回类型限定,不能用于参数类型限定。
经常往里插入的,适合用下界Super,super 可用于参数类型限定,不能用于返回类型限定。
带有 super 超类型限定的通配符可以向泛型对象用写入,带有 extends 子类型限定的通配符可以向泛型对象读取
2.6 对于泛型类的注意事项
-
静态方法中不能使用类的泛型;
-
如果泛型类是一个接口或抽象类,则不可创建泛型类的对象;
-
不能在catch中使用泛型;
-
从泛型类派生子类,泛型类型需具体化;