zoukankan      html  css  js  c++  java
  • 一筐梨子&一筐水果——协变性(covariant)

    假设突然看见这个问题。我们常常会想当然。

    一个梨子是水果,一筐梨子是一筐水果吗


    程序中,我们较少使用到协变性(covariant)。

    一个经典的问题:父类Sup有方法m()。有子类Sub

    public class CovariantDemo{
        public static void main(String[] args) {
            Sub[] b = new Sub[10];
            Sup[] p = b;
    
            p[0] =  new Sup();
            b[0].m();
        }
    }
    有什么问题?

    b是一筐梨子。p是一筐水果,如今你把一个苹果放在了p中。

    所以,编译器觉得正确。执行时java.lang.ArrayStoreException: typeSystem.generics.Sup


    Java泛型中最令人头痛的是參数化类型的协变性问题。

    数组的一个重要性质——协变性(covariant):假设A是B的子类。则A[]是B[]的子类型。


    然而对于泛型C<T>,參数化类型C<Object>与C<String>无关。

    这违反人们的直观认知

    如何说服自己:C<Object>与C<String>无关是合理的。

    (1)參数化类型C<梨子>保证当前有一筐梨子。而C<水果>则保证当前有一筐水果,能够向一筐水果中放入苹果、菠萝。假设C<水果>持有C<梨子>引用却不导致编译错误的话,就能够向一筐梨子中放入苹果、菠萝。那么泛型的作用——保证/限定泛型中元素类型的作用将荡然无存。(技术原因:类型參数的擦除)

    (2)尽管数组具有协变性,可是在使用时,程序猿要自律地限制元素类型、须要做强制类型转换、或者须要忍受执行时异常而非编译时错误。而这些正是Java泛型要避免的,Java泛型比Java数组使用起来更安全。还有一方面,由于可以方便地使用有限定性的数组如“梨子[]”,数组的协变性不被常常使用。也就不显得讨厌。

    (修复例程问题:p[0] =  new Sub(); )


    A是B的子类型。參数化类型C<A> 与C<B>无协变性。在某些情况下,却须要參数化类型可以协变,注意,协变指參数化类型之间的协变。为此,Java提供通配符(wildcard)。包含仅仅读通配符“? extends”和仅仅写通配符“?super”。

    【5.4.2】


  • 相关阅读:
    推荐大家看 《亵渎》
    vue 过滤器filters的使用以及常见报错小坑(Failed to resolve filter)
    vue 与原生app的对接交互(混合开发)
    vue 3.0使用 BUG解决
    202020211 20209313 《Linux内核原理与分析》第一周作业
    2第一周部分笔记
    Cartographer系列之二——hokuyo激光雷达跑cartographer
    ROS系列之初识gmapping
    Cartographer系列之一——初体验
    SLAM学习资料整理
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6986189.html
Copyright © 2011-2022 走看看