好处
- 规定集合的类型,只能传入改泛型限定的类型,避免强转
- 多个类型,执行相同逻辑的代码,避免多次重载。
泛型接口
- 子类实现泛型接口,可以指定它也是泛型 class B<T> implement A<T>
- 子类实现泛型接口,直接implement A<String>
泛型方法
- 指定泛型方法接受的参数和返回值,public <T> T genericMethod(T t){}
- 泛型方法在调用的时候,可以省略<T>, a.<String>genericMethod(“A”);
限定类型变量
extends 上界,<T extends Comparable>,代表T必须是Comparable的子类。可以指定多个类或者接口,如果是一个类,必须放在第一个<T extends ArrayList&Comparable>,且只有一个类;接口可以指定多个;上界对于get是安全的,不允许set,记忆法:eg-> extends get
继承关系:Food->Fruit->Apple->Hongfushi
public static void main(String[] args) {
GenericType<Food> foodGt = new GenericType<>();
GenericType<Apple> appleGt = new GenericType<>();
// print(foodGt); //编译错误,Food不是Fruit的子类
print(appleGt);
// appleGt.setData(new Food()); //编译错误 只能set apple的子类
appleGt.setData(new Hongfushi()); //set ok Hongfushi是apple的子类
Food gFood = foodGt.getData(); //拿到的是Food类型
}
public static void print(GenericType<? extends Fruit> g) {
}
supper 下界,<T super Apple>,代表T必须是Apple的父类。下界对于set是安全的,不允许get,记忆法:ss -> super set
继承关系:Food->Fruit->Apple->Hongfushi
public static void main(String[] args) {
GenericType<Apple> appleGt = new GenericType<>();
GenericType<Hongfushi > hongGt = new GenericType<>();
print(appleGt);
// print(hongGt); //编译错误,Hongfushi不是Appble的父类
Apple apple = new Apple();
Fruit fruit = new Fruit();
Hongfushi hongfushi = new Hongfushi();
appleGt.setData(apple); //set ok
appleGt.setData(hongfushi); //set ok 只能set Apple的子类
// appleGt.setData(fruit); //编译错误,fruit不是Apple的子类
Apple gApple = appleGt.getData(); //可以获取到Apple类型
}
public static void print(GenericType<? super Apple> g){}
泛型中约束和局限性
- 不能实例化泛型变量:T data = new T()(错),可以通过反射newInstance()
- 静态方法不能使用泛型变量:public static T instance(错)
- 泛型只允许引用类型,不适用基本类型:List<int>(错)。如果使用想使用基本类型,需要装箱,如Integer,Long等
- 不能用instanceof判断泛型类型 if(A instanceof List<String>)(错),语法不通过
- 数组不能使用泛型初始化:Restrict<Double>[] a = new Restrict<Double>[](错),可以声明泛型数组,但是不能初始化!
虚拟机如何实现泛型
虚拟机中,采用泛型擦除的方式。
- 对于private T t,不带限定词的,直接擦除为private Object t
- 上界 T extends Comparable&List,擦除后变为 Comparable t
- 下界 T super Apple,擦除后变为Apple a,
- 编译器会在合适的时机,加入强制类型转化,如Map<String,String> map; (String)map.get();