美文网首页
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.协变与逆变原理深度剖析及实例演示

    1.Java中的协变及逆变 Java 中的泛型是不型变的,这意味着 List 并不是 List 的子类型。 为...

  • Kotlin 泛型协变与逆变的理解

    协变与逆变定义 逆变与协变用来描述类型转换后的继承关系 协变:如果 A 是 B 的子类型,并且Generic 也...

  • JAVA泛型与类型安全

    1. 基础泛型 2. 协变与逆变与不变 协变 简单来说即: Java中的数组是协变的 逆变与协变相对,逆转了类型关...

  • Kotlin泛型与协变及逆变剖析

    Kotlin泛型与协变及逆变剖析 关于泛型的使用其实很简单,但是!!如文章开头所说,一直理解不了在Java框架中很...

  • Java协变和逆变

    泛型的协变与逆变 协变与逆变用来描述类型转换(type transformation)后的继承关系,其定义如下:如...

  • 12.Kotlin泛型与协变及逆变原理剖析

    1.密封类 密封类(sealed class)①密封类用来表示受限的类继承结构,对密封类中的某个值来说,它所属类型...

  • Flow中对逆变和协变的处理

    协变逆变不变的解释 协变:f(Employee) extend f(Person) 逆变:f(Person) ...

  • 泛型编程中的型变

    在泛型编程中,经常会提到型变。型变分为两种:协变与逆变。协变covariant表示与泛型参数T的变化相同,而逆变c...

  • Kotlin学习笔记 - 泛型

    1. 基本用法 2. 型变 型变包括 协变、逆变、不变 三种: 协变:泛型类型与实参的继承关系相同 逆变:泛型类型...

  • Java中的逆变与协变

    什么是逆变与协变 协变(Covariance) 如果B是A的子类,并且F(B)也是F(A)的子类,那么F即为协变 ...

网友评论

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

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