美文网首页
13.协变与逆变原理深度剖析及实例演示

13.协变与逆变原理深度剖析及实例演示

作者: leofight | 来源:发表于2018-01-21 10:07 被阅读0次

    1.Java中的协变及逆变

    Java 中的泛型是不型变的,这意味着 List<String> 并不是 List<Object> 的子类型。

    为什么这样? 如果 List 不是不型变的,它就没比 Java 的数组好到哪去,因为如下代码会通过编译然后导致运行时异常:

    List<String> strs = new ArrayList<String>();
    List<Object> objs = strs; // !!!即将来临的问题的原因就在这里。Java 禁止这样!
    objs.add(1); // 这里我们把一个整数放入一个字符串列表
    String s = strs.get(0); // !!! ClassCastException:无法将整数转换为字符串
    

    因此,Java 禁止这样的事情以保证运行时的安全。但这样会有一些影响。

    • 举例说明java中协变与逆变
    class Animal{
    
    }
    class Cat extends Animal{
    
    }
    class Dog extends Animal{
    
    }
    

    协变

    List<Cat> cats = new ArrayList<>();
    List<? extends Animal> animals = cats;//可放Animal及Animal的子类
    animals.add(new Cat());//无法编译通过,协变是生产者(Producer)只能获取,不能添加
    

    逆变

    List<Animal> animals = new ArrayList<>();
    List<? super Animal> contravariantAnimals = animals;
    contravariantAnimals.add(new Cat());
    contravariantAnimals.add(new Dog());
    
    Animal animal = contravariantAnimals.get(0);//无法编译通过,逆变是消费者(Consumer)只能添加,不能获取
    
    • 小结

    带 extends 限定(上界)的通配符类型使得类型是协变的(covariant)。

    List<? super String> 是 List<Object> 的一个超类,称为逆变性(contravariance).

    只能从中读取的对象为生产者,只能写入的对象为消费者。

    PECS: Producer(生产者) Extends, Consumer(消费者) Super.

    2.Kotlin中的协变及逆变

    举例说明
    协变

    class ParameterizedProducer<out T>(private val value:T){
        fun get():T{
            return this.value
        }
    }
    
    fun main(args: Array<String>) {
     
        val parameterizedProducer = ParameterizedProducer("welcome");
        val myRef:ParameterizedProducer<Any> = parameterizedProducer;
    
        assertTrue(myRef is ParameterizedProducer<Any>)
    }
    

    逆变

    class ParameterizedConsumer<in T>(private val value:T){
        fun toString(value:T):String{
            return value.toString()
        }
    }
    
    fun main(args: Array<String>) {
    
        val parameterizedConsumer = ParameterizedConsumer<Number>(1)
        val myRef2:ParameterizedConsumer<Int> = parameterizedConsumer
    
        assert(myRef2 is ParameterizedConsumer<Int>)
    }
    
    • 小结

    在Kotlin中:Consumer in,Producer out

    相关文章

      网友评论

          本文标题:13.协变与逆变原理深度剖析及实例演示

          本文链接:https://www.haomeiwen.com/subject/bhrfaxtx.html