欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java泛型的几点总结

程序员文章站 2022-07-13 15:29:03
...

1 父类是个泛型类,子类继承父类,如果不指定父类的泛型类型或者没有重新声明一个泛型,那么子类讲不是一个泛型类

public class Parent<T> {
   
}

public class Son extends Parent {
}

 下面这样写是会报错的

Son<Integer> song = new Son<Integer>();

2 类型通配符

2.1 <? extends xx>

Number obj = new Integer(123);
List<Integer> integerList = new ArrayList<>();
List<Number> numberList = integerList;

 java对象,父类型可以引用所有的子类实现,如上第一行代码Number引用类型可以引用Integer对象

而List<Number>和List<Integer>没有任何上下级关系,List<Number>是不能引用List<Integer>的,上面的最后一行代码会报错,而数组确可以,因为数组是协变的,如下代码是合法的

Integer[] integerArry = new Integer[1];
Number[] numberArry = integerArry;

 类似Number引用Integer,如果我想用List<Number>引用List<Integer>怎么办?

List<? extends Number>就是用来解决这个问题的,除了Integer,任何继承自Number的类都可以引用。

通过类型通配符List<? extends Number>引用会产生副作用:

(1)可以get列表中的值,并且用Object或Number来引用这个值。

          Object好理解,它可以引用任何类型

          由于List<? extends Number>所引用的列表中的元素类型一定是Number的子类型,所有可以用Number引用也好理解

(2)不能set除了null以外的任何值

          因为List<? extends Number>可以引用任何Number子类型的List,具体是哪一个,无法得知,也是就是不知道List中的原始是什么类型(只知道是Number的子类型),所以也就无法set元素。

说了半天,List<? extends Number>究竟是用来解决什么问题的?难道仅仅是引用更多类型参数的List吗?或者说,引用更多类型参数的List可以达到什么目的?假设有这样一个场景,提供一个方法,方法的入参是List<Number>,这个方法的逻辑就是把这个列表中的值取出来,执行某些操作。取出元素后,通过Number来引用元素,然后执行某些操作,代码完全是针对Number类型来写的。理论上针对Number类型写的代码,同样适用于Number的所有子类(面向接口编程),所以泛型类型是Number子类的List,也可以在这个方法中得到正确的处理。但是我们怎么才能支持,所有泛型类型是Number子类的list可以传递到这个方法中,List<Number>肯定不支持,List<? extends Number>正好可以满足这个需求。请注意,仅仅是把列表中的元素取出来,如果要往这个列表中set元素,这是List<? super Number>所要解决的问题。
2.2 <? super xx>

 List<? super Number>可以引用任何泛型类型是Number或这Number父类的List

List<? super Number>副作用:

(1)可以取出原始,但是只能被Object引用。父类型不确定是哪一个,所有只能用最顶层类型Object引用

(2)只能设置null或者Number的任何子类型,包含Number。java中父类型可以引用任何子类型,<? super Number>可以确定的是,元素类型一定是Number的父类型,所以Number或者它的子类型,一定可以被引用,所以理所当然的就可以被设置进去。

用来解决什么问题,加上有个方法的入参是List<Number>,这个方法的逻辑就是往这个列表中set元素,由于java父类型可以医用子类型,所有Number任何的子类型都可以设置进去。想象一下,这个方法往List中set原始的代码,是否也同样适用于List<Object>,其实任何Number的父类都适合,那怎么把泛型类型是Number的父类的list传递到这个方法呢?把方法的入参声明成List<? super Number>就可以达到这个目的

 

List<? extend Number>和List<? super Number>的区别:

List<? extend Number>为取出元素而生,List<? super Number>为设置进元素而生,在Effective Java一书中,把这一原则称为:PECS原则。