泛型
generics ,本质是参数化类型 ,所操作的数据类型被指定为一个参数
常用字母:T、V、K、E
为什么需要泛型
1、多种数据类型执行相同的代码
public addInt(int x,int y){
}
public addFloat(int x,int y){
}
2、泛型类型在使用时,不需要强制类型转换
image.png
泛型类
image.png
泛型接口
image.png
泛型接口的两种实现方式
1、不传入泛型实参
public class ImplGenerator implements Generator{
private T data;
}
// 在new的时候需要指定具体类型
2、传入泛型实参
public class ImplGenerator2 implements Generator{
}
//在new的时候和普通类 没区别
泛型方法
方法前面必须要有
可以再普通类中使用
public class GeneratorMethod{
public T genericMethod(T ...a){ //必须要有
return a[a.length/2];
}
public static void main(String[] args) {
GenericMethod genericMethod = new GenericMethod();
genericMethod.test(23,343);
System.out.println(genericMethod.genericMethod("mark","av","lance"));
System.out.println(genericMethod.genericMethod(12,34));
}
}
extends (类型变量的限定) 继承、派生
1、限定T 必须要实现Comparable接口
public static T min(T a ,T b){
if(a.compareTo(b)>0){//需要给T加限定实现Comparable接口,现在报错
return a;
}else{
return b;
}
}
//加限定如下
public static T min(T a ,T b){
if(a.compareTo(b)>0){ //需要给T加限定实现Comparable接口,现在报错
return a;
}else{
return b;
}
}
2、限定类 , 限定类要写在限定接口前
// T extends ArrayList&Comparable ; ArrayList 要写在 Comparable前,不然报错
public static T min(T a, T b){
if(a.compareTo(b)>0) return a; else return b;
}
泛型的约束和局限性
1、不能实例化类型变量
public class Restriction {
public Restriction(){
this.data = new T();//这里就不能实例化!!!
}
}
2、静态域或者方法里边不能引用类型变量
private static T instance;//这里就报错了,static是在类加载的时候就开始执行了,T 需要在构造的时候才能初始化,此时引用不到T
3、基本类型不能当泛型对象使用
即:byte、short、int、long、float、double、boolean、char 不能当泛型对象使用
如:Restrict 就不行,只能是基本类型的包装类型Restrict
```
4、泛型不能使用instanceof
例如, 无法写成这样:
if(restrict instanceof Restrict)
if(restrict instanceof Restrict)
5、getClass()
例如:
Restrict stringGen = new Restrict<>();
Restrict doubleGen = new Restrict<>();
System.out.print(stringGen.getClass() ==doubleGen.getClass());
// 输出结果是true
//直接打印它两的Name一致
System.out.print(stringGen.getClass().getName()) ;
System.out.print(doubleGen.getClass().getName());
//结果如下:
com.example.Restrict
com.example.Restrict
6、可以声明泛型数组,但是不能实例化
Restrict[] resArray;//可以申明
// Restrict[] resArray = new Restrict();//这样就报错了
7、不能捕获泛型对象,但是可以抛出
//不能捕获:
public void doWork(T t){
try{
}catch(T t){ //这里编译器就会报错
}
}
//可以抛出
public void doWorkSuccess(T x) throws T{
try{
}catch(Throwable e){
throw x;//这个没有问题
}
}
泛型类型的继承规则
1、现有类 Employee extends Worker
2、Pair类
class Pair{
}
3、Pair和Pair没有任何继承关系
Pair = new Pair<>();
Pair = new Pair<>();
如:
Employee employee = new Worker();
// Pair employee2 = new Pair(); 这样就会报错
image.png
通配符
用在方法参数上,不能用在类上
? extends Fruit(类型的上界)(包括fruit的子类和fruit本身)
image.png
image.png
赋值
image.png
限定了传入参数的上界,可以取,但是不能设置
主要用于安全的访问数据,可以访问extends 后面的
image.png
? super Apple
Apple的超类
主要是安全的写入数据
image.png
只能设置Apple 子类 【子类可以安全的转型为Apple】
image.png
返回类型只能是Object
image.png
虚拟机如何实现泛型
类型擦除,在相应的地方插入了强制转型代码
public class Theory {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("king","18");
System.out.println(map.get("king"));
}
}
image.png