gpt4 book ai didi

java - Java中数组的协方差有什么好处?

转载 作者:行者123 更新时间:2023-11-30 10:01:05 25 4
gpt4 key购买 nike

这个概念似乎不是很容易理解,或者网上那么多长篇文章都没有很好地解释。如果有人能以清晰而简短的方式解释,我将不胜感激。

我已阅读 this blog 中的示例和 this video .

目前我得出的结论是:

在 Java 中,数组是协变的,泛型是不变的。

  1. 数组是协变的:

    Number[] myNums = new Integer[3]; // compile ok

    但是..如果我这样做,虽然编译正常但运​​行时错误:

    myNums[0] = 2.1; // compile ok, run time not ok 

    如果运行时不正常,数组协变有什么意义?这个问题其实可能指的是“协变有什么意义?”

  2. 泛型是不变的:

    List<Number> myNums = new ArrayList<Integer>(); // compile not ok 
  3. 但令人惊讶的是,有一种方法可以使泛型协变/协变,使用通配符:

    List<? extends Number> myNums1 = new ArrayList<Integer>(); // convariance, compile ok 


    List<? super Integer> myNums2 = new ArrayList<Number>(); // contravariance, compile ok
  4. 即使有办法让它协变或逆变,我还是做不到这样的事情

    myNums1.add(New Integer(1));

这一切的意义何在?

拜托,有没有人帮我解决所有这些困惑?

最佳答案

In Java, arrays are covariant and generics are invariant.

是的数组。对于 Java,它适用于没有通配符的泛型,但带有通配符的泛型超越了这个限制。

What is the point of having array covariant if run time will be NOT ok?

没有值(value)。这是一个数组特定的缺点,没有像在泛型中那样重现。

What is the point of all of this?

关于 Java 泛型,关键是它们不是绝对不变的、协变的或逆变的,因为不变是更安全的方式,但它在编程特性方面也是最具限制性的。我在下面举例说明。
因此 Java(以及其他强类型语言)选择提供不同的泛型风格:不变、协变和逆变,同时在任何情况下都确保类型安全(当然你要尊重编译器警告)。

But amazingly, there's a way to make generics covariant/cotravariant, use wildcard:

其实并不奇怪。如果没有协变性,您将失去在接受该变量父类(super class)型的方法中传递以泛型类型声明的变量的所有可能性。如果此方法只读取作为参数传递的通用变量,并且编译器可以确保:您在运行时没有类型存储问题,因为您没有在其中添加任何内容。所以你想使用上限通配符。

List<Integer> integers = ...;
List<Long> longs = ...;
List<Float> floats = ...;
doThat(integers); // compile ok
doThat(longs); // compile ok
doThat(floats); // compile ok

//...
public void doThat(List<? extends Number> list){
for (Number n : list){ // compile ok : reading
//...
}
// but the compiler doesn't allow to store
list.add(Integer.valueOf(1));
}

同样,如果没有逆变,您将失去在通用类型中安全添加内容的所有可能性。如果编译器确保逆变是安全的,因为我们只能在传递给的泛型类型变量中添加父类(super class)型的东西,为什么要失去这种能力?所以你想使用下界通配符。

List<Integer> integers = ...;
List<Long> longs = ...;
List<Float> floats = ...;
List<Number> numbers = ...;
doThat(integers); // compile ok
doThat(numbers); // compile ok
doThat(longs); // compile fails
doThat(floats); // compile fails

//...
public void doThat(List<? super Integer> list){
// the compiler allows to add that as type safe
list.add(Integer.valueOf(1));
// but it doesn't allow to add no safe things
list.add(Float.valueOf(1f));
}

关于java - Java中数组的协方差有什么好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57644227/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com