Java语言中的泛型则不一样,它只在程序源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码,因此,对于运行期的Java语言来说,ArrayList<int>与ArrayList<String>就是同一个类,所以泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型。
A<String> aString= new A();
A<? extends Object> aInteger = aString;
A<Object> aObject = new A();
A<? super String> aSuper = aObject;
通过匿名内部类获取父类的元数据定义,来获取type,获取泛型的具体类型。
static class A<T> {
T a;
}
public static final void main(String[] args) {
ArrayList list = new ArrayList<String>(){};
A a = new A<Integer>(){};
System.out.println(a.getClass().getGenericSuperclass());
System.out.println(list.getClass().getGenericSuperclass());
ParameterizedType parameterizedType = (ParameterizedType)a.getClass().getGenericSuperclass();
Type type = parameterizedType.getActualTypeArguments()[0];
System.out.println("A类型变量泛型 type: "+type);
}
java 协变逆变
static class Fruit{}
static class Apple extends Fruit{
@NonNull
@Override
public String toString() {
return "Apple";
}
}
// 上界通配符只适合 out 数据 ,通过get访问数据
List<? extends Fruit> fruitsOut = apples;
Fruit fruit = fruitsOut.get(0);// Fruit 类型范围大于get获取的类型
// fruitsOut.add(new Apple()); // 无法确认添加的lei'xing
// 下界通配符只适合in 数据, 通过add 添加数据
List<? super Fruit> fruitsIn = new ArrayList<>();
fruitsIn.add(new Apple());// fruitsIn类型范围大于Apple
// Fruit object = fruitsIn.get(0); // 报错无法识别get获取到类型
kotlin 协变逆变
interface Source<out T> {
fun nextT(): T
}
fun demo(strs: Source<String>) {
val objects: Source<Any> = strs // 这个没问题,因为 T 是一个 out-参数
}
interface Comparable<in T> {
fun compareTo(other: T): Int
}
fun demo(x: Comparable<Number>) {
x.compareTo(1.0) // 1.0 拥有类型 Double,它是 Number 的子类型
// 因此,我们可以将 x 赋给类型为 Comparable <Double> 的变量
val y: Comparable<Double> = x // OK!
}
参考:
Java泛型的协变、逆变和不变
深入理解Kotlin中的泛型(协变、逆变)
Java泛型的定义和使用详解
Java泛型的协变、逆变和不变
PECS(Producer Extends Consumer Super)原则
kotlin官方