这里写自定义目录标题
- 一、什么是泛型
- 二、为什么需要泛型?
- 三、自定义泛型结构
- 1、泛型类
- 2、泛型方法
- 四、泛型在继承上的体现
- 五、通配符的使用
- 1、注意点
- 2、有限制的通配符
一、什么是泛型
泛型就是定义类、接口时通过一个标识表示类中某个属性的类型 、方法的返回值类型、参数类型。
这个类型参数将在使用时确定
二、为什么需要泛型?
Java泛型保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。
三、自定义泛型结构
1、泛型类
在类或者接口的后面申明了泛型,则该类或者接口就称为泛型类
- 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如:<E1,E2,E3>
- 泛型类的构造器如下:public GenericClass(){}。而下面是错误的:public GenericClass(){}
- 在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型
- 父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:
-
子类不保留父类的泛型:按需实现
-
没有类型 擦除
class Father<T1, T2> {}// 子类不保留父类的泛型
// 1)没有类型 擦除
// 等价于class Son extends Father<Object,Object>{
class Son1 extends Father {} -
具体类型
class Son2 extends Father<Integer, String> {}
-
-
子类保留父类的泛型:泛型子类
- 全部保留
class Son3<T1, T2> extends Father<T1, T2> {} - 部分保留
class Son4 extends Father<Integer, T2> {}
- 全部保留
-
class Person<T> {
// 使用T类型定义变量
private T info;
// 使用T类型定义一般方法
public T getInfo() {
return info;
}
public void setInfo(T info) {
this.info = info;
}
// 使用T类型定义构造器
public Person() {
}
public Person(T info) {
this.info = info;
}
}
2、泛型方法
在方法中出现了泛型结构,泛型参数与类的泛型没有任何关系(泛型方法所属的类是不是泛型类都不要紧)
泛型方法的格式:
访问权限 <泛型> 返回类型 方法名(泛型标识 参数名称) 抛出异常
public class DAO {
public <E> E get(int id, E e) {
E result = null;
return result;
}
}
四、泛型在继承上的体现
如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的类或接口,G并不是G的子类型!
比如:String是Object的子类,但是List并不是List的子类。
五、通配符的使用
List<?>是List、List等各种泛型List的父类。
不能向 List<?> list 中添加元素,但是可以添加null
我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object。
1、注意点
-
不能用在泛型方法声明上,返回值类型前面<>不能使用?
-
不能用在泛型类的声明上
-
不能用在创建对象上,右边属于创建集合对象
2、有限制的通配符
-
通配符指定上限
上限extends:使用时指定的类型必须是继承某个类,或者实现某个接口,即<= -
通配符指定下限
下限super:使用时指定的类型不能小于操作的类,即>=
举例:
<? extends Number> (无穷小 , Number] 只允许泛型为Number及Number子类的引用调用 <? super Number> [Number , 无穷大) 只允许泛型为Number及Number父类的引用调用 <? extends Comparable> 只允许泛型为实现Comparable接口的实现类的引用调用 # 六、泛型使用举例