ps:标题中的圆括号应该为尖括号,否则,标题非法,发表不出去。
?表示类型通配符,即具体传什么参数类型,在List定义时不用考虑。
这里的<>表示泛型,T表示泛型中装载的类型为T类型,等到需要的时候,我们可以具体这个T。我们在使用动态数组实现ArrayList的时候,如果希望这个ArrayList不仅仅支持一个类型的话,我们可以给这个ArrayList定义泛型,泛型中存放的是T类型。在实际创建出这个ArrayList对象时,我们可以指定泛型中的具体类型。
类型上界。表示的是此处我们传入的类型必须是T类型本身或其子类。如果这里的T为Number的话,那么我们只能传入Number本身或其子类,比如Integer,Floart等基本数据类型的包装类。
类型下界。表示的是此处我们传入的类型必须是T类型本身或其超类。如果这里的T为Integer的话,那么我们只能传入Integer本身或其超类,比如Number类。
extends T>是被设计用来读取数据的泛型,并且只能读取类型为T的元素。原因如下:
我们现在知道,此List中存放的都是T类型或其子类,因此,我们可以这样做来读取元素。
List extends Number> list = new ArrayList<>();
Number number=list.get(0);
使用Number类型,即T类型来接受本身类型或其子类类型的元素。
当然这样的赋值也是合法的
List extends Number> integers = new ArrayList();
List extends Number> floats = new ArrayList();
他为什么不能增加元素?原因如下:
编译器仅仅通过List extends Number>来了解到,这个List中可以存放Number本身和其子类,但具体是什么它不知道,即使在等号后面使用new ArrayList
但是!虽然不能add元素,但可以在初始化的时候,接受一个已经定义好的list,而该list存放的类型一定相同,因此,List extends T>可直接接受一个定义好的list。
public static List getList(){
List list=new ArrayList<>();
list.add(1);
return list;
}
....
public static void main(String[] args) {
List extends Number> list = new ArrayList<>();
list=getList();
}
List super T>是被设计用来添加数据的泛型,并且只能添加T类型或其子类类型的元素。
我们知道,此List中存放的元素一定是T类型或其父类类型的元素,由于编译器不确定到底是什么类型,我们可以这样来添加元素。
List super Integer> list2 = new ArrayList<>();
list2.add(new Integer(1));
list2.add(new Double(1.0));//编译错误,Double不为Integer的子类
由于编译器不知道我们需要什么类型,因此在获取元素的时候,总是返回Object类型,因此我们使用Object类型来接受获取到的元素。
List super Integer> list2 = new ArrayList<>();
list2.add(new Integer(1));
Object integer=list2.get(0);
如果我们非要使用List super Integer>中的Integer类型来接收获取到的元素,那么必须进行强制类型转换。
List super Integer> list2 = new ArrayList<>();
list2.add(new Integer(1));
Integer integer1= (Integer) list2.get(0);
如果我们使用Object类型来接收获取到的元素,那么元素本身的类型就会丢失,因此,我们不使用List super T>来获取元素。
(1)List extends T>适用于读取数据,读取出来的数据全部用T类型接收。如果我们往此list中添加T类型不同的子类的话,各种子类无法相互转换,因此不能添加元素,但可接受初始赋值。
(2)List super T>适用于添加元素,只能添加T类型或其子类类型。因为这些类型都能转换为?表示的类型(向上转型),因此我们可以对此list添加元素。只能用Object类型来接收获取到的元素,但是这些元素原本的类型会丢失,因此最好不要使用此泛型来获取元素。