Java VS kotlin 泛型

java 虚拟机泛型实现(伪泛型)

Java语言中的泛型则不一样,它只在程序源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码,因此,对于运行期的Java语言来说,ArrayList<int>与ArrayList<String>就是同一个类,所以泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型。

Java 通配符

A<String> aString= new A();
A<? extends Object>  aInteger = aString;

A<Object> aObject = new A();
A<? super String> aSuper = aObject;

获取泛型type

通过匿名内部类获取父类的元数据定义,来获取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);
    }

协变逆变 - 生产者消费者

  1. 生产者->协变->kotlin: out->java: (上界通配符)
  2. 消费者->逆变->kotlin: in ->java: (下界通配符)
  3. PECS(producers extends, consumers super)
    生产者适合out,因为编译器不知道具体类型是什么子类,无法赋值,但是可以取出来作为Object
    消费者适合in,因为任何父类都可以作为输入,但是无法取出赋值给具体的类型
  4. 赋值语句左边类型必须大于右边类型
  5. 函数返回类型必须大于函数体内真实返回对象类型

实战

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  的变量
    val y: Comparable<Double> = x // OK!
}

参考:

Java泛型的协变、逆变和不变
深入理解Kotlin中的泛型(协变、逆变)
Java泛型的定义和使用详解
Java泛型的协变、逆变和不变
PECS(Producer Extends Consumer Super)原则
kotlin官方

你可能感兴趣的:(java,kotlin,开发语言)