Java中泛型的使用
文章目录
泛型的理解
泛型的概念
所谓泛型,就是允也称为许在定义类、接口时通过一个标识表示类中的某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口时,用这个类型声明变量、创建对象时确定[即传入实际的类型参数,也称为类型实参])。
泛型的引入背景
集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的 对象,所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来 解决。因为这个时候除了元素的类型不确定 ,其他的部分是确定的,例如关于 这个元素如何保存 ,如何管理等是确定的,因此此时把元素的类型设计成一个 参数,这个类型参数叫做泛型。Collection
泛型在集合中的使用
在集合中使用泛型之前的例子
|
|

在集合中使用泛型例子1
|
|

在集合中使用泛型例子2
|
|
在集合中使用泛型总结
-
集合接口或集合类在JDK5.0时修改为带泛型的结构。
-
在实例化集合类时,可以指明具体的泛型类型。指明完之后,在集合类或接口中凡是定义类或者接口时,内部结构(比如:方法、构造器、属性等使用到类的泛型的位置,都指明为实例化的泛型类型)。
比如:add(E e)————>实例化后:add(Integer e)
-
泛型的类型必须时类,不能时基本数据类型,如果要用到基本数据类型的地方,需要使用其包装类类型替代。
-
如果实例化时没有指明泛型的类型,默认类型为java.lang.Object类型。
-
JDK7之后,可以使用类型推断:
1 2 3 4// 原来: ArrayList<Integer> list = new ArrayList<Integer>(); // JDK7之后: ArrayList<Integer> list = new ArrayList<>();
自定义泛型、泛型接口、泛型方法
-
泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如: <E1,E2,E3>
-
泛型类的构造器如下:public GenericClass(){}。 而下面是错误的:public GenericClass
(){} -
实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致。
-
泛型不同的引用不能相互赋值。
尽管在编译时ArrayList
和ArrayList 是两种类型,但是,在运行时只有 一个ArrayList被加载到JVM中。
-
泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价 于Object。经验:泛型要使用一路都用。要不用,一路都不要用。
-
如果泛型结构是一个接口或抽象类,则不可创建泛型类的对象。
-
jdk1.7,泛型的简化操作:ArrayList
flist = new ArrayList<>(); -
泛型的指定中不能使用基本数据类型,可以使用包装类替换。
-
在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态 属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。
-
异常类不能是泛型的
-
不能使用new E[]。但是可以:E[] elements = (E[])new Object[capacity];
需要先定义为Object类型,再进行类型强转成E类型的。
参考:ArrayList源码中声明:Object[] elementData,而非泛型参数类型数组。
- 父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
-
子类不保留父类的泛型:按需实现
- 没有类型 擦除
- 具体类型
-
子类保留父类的泛型:泛型子类
- 全部保留
- 部分保留
结论:子类必须是“富二代”,子类除了指定或保留父类的泛型,还可以增加自 己的泛型
-
泛型方法的使用:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有关系。
1 2 3 4// 定义泛型方法需要在前面声明泛型类型,并使用尖括号包裹起来:<E> public <E> List<E> copyFromArrayList(E[] arr){ }
泛型在继承上的体现
如果B时A的一个子类型(子类或者子接口),而G时具有泛型声明的类或接口,则G并不是G的子类型!
比如:String是Object的子类,但是List

|
|
通配符
通配符的使用
使用类型通配符:?。
比如:List<?>,Map<?,?>等。List<?>是List
|
|
涉及通配符的集合的数据的写入和读取
-
读取
读取List<?>的对象list中的元素时,永远是安全的,因为不管?代表的是什么类型,它总是包含有Object的。
-
写入
无法写入list中的元素,因为我们并不知道list的元素类型,无法添加确认的元素对象。
唯一例外的是null,它是所有类型的成员。
1 2 3List<?> list = new List<String>(); list.add(null);
通配符使用的注意点
-
不能用在泛型方法声明上,返回值类型前面<>不能使用?
1 2public static <?> void test(ArrayList<?> list){ } -
不能用在泛型类的声明上
1 2class GenericTypeClass<?>{ } -
不能用在创建对象上市,右边属于创建集合对象
1ArrayList<?> list2 = new ArrayList<?>();
有限制条件的通配符的使用
- >:允许所有泛型的引用调用
-
上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<=
1 2<? extends Number> (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用 -
下限super:使用指定的类型不能小于操作的类,即>=
1 2<? super Number> [Number,无穷大] 只允许泛型为Number及Number父类的引用调用
例子:
|
|
【练习题】
|
|
文章作者 Bearkchan
上次更新 2020-03-02