美文网首页
java----对java以及Kotlin中泛型型变的相关认识!

java----对java以及Kotlin中泛型型变的相关认识!

作者: 不过意局bugyj | 来源:发表于2018-09-05 09:27 被阅读0次

泛型是一个很令人费解的概念,但却是理解类型系统的重要基石!


  大部分内容摘自《kotlin极简教程》,加上了自己的一些理解,写的不好,请多指教!

型变有三种基本的形态:协变(covariant), 逆变(cotravariant),不变(invariant)

  我们先从java了解的类型通配符介绍这三个概念:java中通配符有一下两种形式:

? extends T:子类型上界限定符,指定类型的上界(只能是T类型或者T的子类)
? super T :父类的下界限定符,指定类型的下界(只能是T类型或者是T类型的父类)

interface Animals{
    void eat();
    void run();
}
class Cat implements Animals{
    @Override
    public void eat() {}
    @Override
    public void run() { }
}
class Dog implements Animals{
    @Override
    public void eat() {}
    @Override
    public void run() {}
}

  在这里我先用java写几个类,在java中我们知道:Animal是Cat和Dog的父类,可以直接使用Cat的子类和Dog的子类给Animals的一个对象赋值,那么ArrayList<Animals> animals = new ArrayList<Cat>()或者ArrayList<Animals> animals = new ArrayList<Dog>()还可以吗?或者说ArrayList<Animals>还是ArrayList<Cat>()或者ArrayList<Dog>的父类吗?

我们试试看:

  可以看到编译报错,所以是不可能这样赋值的!

  那么泛型通配符就派上用处了。将ArrayList<Animal> animals改成 ArrayList<? extends Animal> :

  也就是说ArrayList<Animals>并不是ArrayList<Cat>()和ArrayList<Dog>的父类,而ArrayList<? extends Animals>才是!

  这里的ArrayList<? extends Animals>并不能添加Animal及其子类对象的!因为如果能的话就既能添加Cat对象又能添加Dog对象,java是不允许的!但是能add(null)

  上述这种情况就叫做协变(即F是C的父类,f(F)是f(C)的父类)所以<? extends T>实现了泛型的协变!(f(F)类似于List<F>的形式)

<? super T>实现了泛型的逆变!

  逆变即(即F是C的父类,f(C)是f(F)的父类)

如果既不是逆变又不是协变,就是不变。

  List<? super Number>,这里限制了List的内容只能是Number和Number父类。例如List<Object> 就是他的子类,而Object是所有类的父类,这就是逆变!看代码:

ArrayList<Number> numbers = new ArrayList<Object>()报错!


  ArrayList<? super Number> numbers = new ArrayList<Object>()编译通过!

  在这个list中我们不能添加Number的任一父类对象,但能添加Number和其所有子类的对象!

PECS(Producer-Extends, Consumer-Super)

  那么我们什么时候使用extends,什么时候使用super呢!

  《kotlin极简教程》书上用了一个stack API来举例说明:

public class Stack<E>{
    public Stack(){}
    public void push(E v){}
    public E pop(){}
    public boolean isEmpty(){}
}

  实现pushAll方法

    public void pushAll(Iterable<E> src){
        for(E e : src)
            push(e)
    }

  假设有一个实例化的stack<Number>,要将stack<Integer>和stack<Float>里的所有值添加进去,调用上面的方法会出现type mismatch错误应该写成下面这种形式。

    public void pushAll(Iterable<?extends E> src){
        for(E e : src)
            push(e)
    }

  而要实现popAll方法,将一个stack中的元素依次取出add至dst中,不用通配符时:

    public void popAll(Stack<E> dst) {
        while(!isEmpty())
            dst.push(pop())
    }

  如果要将一个stack<Number>栈全部输出至一个stack<Object>中, 即dst是stack<Object>类,则一样会出现type mismatch错误,应将方法改成:

    public void popAll(Stack<? super E> dst) {
        while(!isEmpty())
            dst.push(pop())
    }

  将其PECS称为Get and Put principle

  在java.util.Collection的copy方法中完美地诠释了PECS:

    public static <E> void copy(List<? super E> dest, List<? extends E> src) {
        int srcSize = src.size();
        if(srcSize > dest.size())
            throw new IndexOutOfBoundsException("Source does not fit in dest");
        ...略
    }

  大致可以这么解释,在这个方法中,我们从src中取数据,即src是producer,然后将数据添加至dest,所以dest是consumer所以,PECS,前者就是super,后者就是extends。

kotlin:

 java中有通配符,kotlin中则抛弃了这些,引用了生产者消费者概念,从上面的copy方法中也可以看出端倪。

  kotlin把只负责安全读取数据的对象称为生产者,只负责安全写入数据的对象为消费者。kotlin中,生产者用

<out T>(等价于<? extends T>),消费者用<in T>(等价于<> super T>)。

相关文章

  • java----对java以及Kotlin中泛型型变的相关认识!

    泛型是一个很令人费解的概念,但却是理解类型系统的重要基石!   大部分内容摘自《kotlin极简教程》,加上了自己...

  • Kotlin 泛型

    Kotlin 中也有泛型的概念,和 Java 中的类似,但又不尽相同,一起来认识 Kotlin 中的泛型吧。 一、...

  • Kotlin 泛型

    Kotlin 支持泛型, 语法和 Java 类似。例如,泛型类: 泛型函数: 类型变异 Java 的泛型中,最难理...

  • Kotlin型变

    Java的泛型不支持型变,Java采用通配符来解决这个问题;Kotlin采用安全的型变代替了Java的通配符。 一...

  • Kotlin泛型入门

    Kotlin也提供了泛型的支持,Kotlin提供了声明处型变和使用处型变两种支持,而Java只支持使用处型变。 一...

  • Kotlin学习笔记(七)-泛型

    [toc] 前言 这节我们说下Kotlin的泛型。首先默认大家对Java泛型有个基本的认识,如果 不熟悉Java的...

  • 泛型

    与Java泛型相同,Kotlin同样提供了泛型支持。对于简单的泛型类、泛型函数的定义,Kotlin 与 Java ...

  • 教你如何完全解析Kotlin中的注解

    简述: 从这篇文章将继续开始探索Kotlin中的一些高级的内容,之前有着重探讨了Kotlin的泛型以及泛型型变等内...

  • Kotlin 泛型

    说起 kotlin 的泛型,就离不开 java 的泛型,首先来看下 java 的泛型,当然比较熟悉 java 泛型...

  • Kotlin 泛型 VS Java 泛型

    建议先阅读我的上一篇文章 -- Java 泛型 和 Java 泛型一样,Kotlin 泛型也是 Kotlin 语言...

网友评论

      本文标题:java----对java以及Kotlin中泛型型变的相关认识!

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