Java的泛型和原理

86 阅读2分钟

泛型的出现

在没有泛型的年代,ArrayList这些集合类可以存放所有类型的对象,都是以object的方式存储,取用的时候,需要一次强制转换,这是一个风险操作,会出现ClassCastExcetion,泛型的出现就是解决这个问题的

泛型的作用

1.编译时类型检查 2.运行时自动转型

怎么使用呢?

在类上定义和使用

public interface Shop<T>{ 
    T buy(); 
    float refund(T item);//退货 
}

在方法上定义和使用

public <T> T get(T t){ 
    return t; 
}

泛型的继承(泛型类型实例化了)

public interface Shop<T>{ 
    T buy(); 
    float refund(T item);//退货 
} 
public AShop implements Shop<Apple>{ 
    Apple buy(); 
    float refund(Apple apple); 
}

泛型的继承(传递,但并不实例化)

public interface ReparableShop<T> extends Shop<T>{//ps:泛型是个记号,代表这边有需要实例化的类型,需要后续填充类型 
    void repare(T item); 
} //T的作用范围只有本类

多个泛型,多个需要实例化类型的泛型

public interface ReparableShop<T,C> extends Shop<T>{//ps:泛型是个记号,代表这边有需要实例化的类型,需要后续填充类型 
    void repare(T item); 
    C get(String name,int id); 
}

如何实例化

class SimpleShop implements ReparableShop<Apple,ChinaUnicom>{ 
}//实例化泛型,放在基类后面

控制泛型的范围(上限,父类指定)

public interface ReparableShop<T,C extends Sim & Activity>{//Sim可为接口,也可以是类,&可限定多个上限 
    void repare(T item); 
    C get(String name,int id); }

泛型的PECS

Producer extends Customer super记住super可写,extends可读

ArrayList<Fruits> fruits = new ArrayList<Apple>();(❌错误) 
当放入香蕉时,就不符合,左边的条件宽,会导致插入协议不符合条件的元素 

ArrayList<? extends Fruits> fruits = new ArrayList<Apple>();//不能用add 
编译不报错,但所有的类型方法都会执行出错,因为类型未确定,而时间的list类型又确定了,导致无法添加元素 不过这种做法是有对于的需求的,如下图,有一个现成的list,计算它的重量,但副作用是,无法编辑元素或无法使用有类型参与的方法 

ArrayList<? super Apple> fruits = new ArrayList<Fruits>();//不能用get 也可以编译通过,这是设置下界,在方法传递参数的时候可以使用 
? super Apple:表示能接受我Apple类型 
? extends Fruits:继承

泛型的擦除

怎么发现的:编译成class文件之后,再反编译回来就可以看到,或者直接使用ASM bytecode Viewer工具直接看

为什么?保证兼容性,在Java1.5出现的

都擦了吗?没有,这个比较误导人的地方,它擦了,但没有擦干净,使用的地方全部擦了,但声明的地方被保存到class的signature中,后期还可以通过class.getGenericSuperClass获取到类型,Gson解析中的泛型就是通过生成内部类的方法保存住泛型的

TypeToken<List<String>> token = new ThpeToken<List<String>>(){};
看这里有个匿名内部类