泛型
泛型Generic:
一、概述
Java是个强类型的语言,但是Java集合在开始设计之初因为不能明确容器里存放的内容,所以就按照Object 类型设计;但是Java1.5以后引入了类型参数的概念,允许我们定义容器里的内容。而这个类型参数就是泛型。
泛型就是一个标签,规范了容器类的存放数据的类型。可以保证我们在存入数据的安全一致性,也能使得我们在获取数据时减少了向下转型操作;
二、怎么使用泛型
2.1泛型的自定义
泛型可以在我们定义类、接口的时候通过标识符表示该类、接口中某个属性的类型(泛型类/接口);也可以在方法的返回值和参数中使用泛型(泛型方法);
2.2泛型的赋值:
我们给类、接口、方法定义了泛型参数后,必须要给他赋值。如果没有赋值就使用,编译器就会报错。类和接口要在创建对象时就给他赋值,而方法时在调用的时候才给他赋值。因为这个特点所以泛型类和接口的泛型参数不能定义在静态方法 中,因为还没有实例化赋值呢,他们就被调用。编译器就蒙了。。不认识,也找不到类呀。但是泛型方法就跟自由一点,因为要等到调用才给他赋值呢。如果没有给他们赋值,就会默认赋值Object。这样泛型就失去意义,所有泛型要用就一用到底,要不就不用。
三、标签的继承问题
当父类使用了泛型时,子类是否继承了父类的标签呢?答案是随便,子类可以继承父类的泛型参数,也可以不继承,也可以继承一半,另外一半不继承,也可以根据自己的需求添加泛型参数;
四、泛型的通配符 ?
4.1 产生的原因
这就尴尬了,test1方法调用不了了。所以通配符就来了:
编译器为什么会编译报错呢?因为泛型的核心思想是将容器里的内容限定为一个特定的数据类型。
如果List<Object> list 和 List<String> list1不是一个并列结构就会违背这个思想;
当我们在list1中添加数据,如果是继承结构那么list就能获得list1的引用而操作同一个内存空间;list是object类型,可以在内存空间中添加数值型数据;这就导致list1中的String类型数据中混入数值型数据。
4.2
如果A和B是父子类,那么A<Integer>和B<Integer>是父子类。泛型类的构造器不能加泛型,会编译报错;
4.3通配符的使用
1、 List<?>
2、List<? extends A> 表示所有继承A的类,包括A
3、List<? super A> 表示所有A的父类,包括A