当前位置: 首页 > 知识库问答 >
问题:

为什么泛型在“?允许扩展Klass”时说是不变的?

杨曜瑞
2023-03-14

Java说:

String[] is subtype of Object[]

所以说数组是协变的。但对于泛型,他们说:

List<X> will not be subType of List<Y>.

因此它是不变量。但问题是,“泛型真的不变吗?”?

例如,如果我给出:

List<? extends Exception>

这意味着列表可以采用异常的子类型,例如这是有效的:

List<? extends Exception> k = new ArrayList<NumberFormatException>();

那么为什么泛型被称为不变量呢?

共有3个答案

戚令秋
2023-03-14

数组在java中是协变的,但它们不应该是。这只是java语言中的许多设计缺陷之一,尤其是键入系统。考虑以下代码:

public void messUp(Object objects[]) { objects[0] = "foo"; }
Integer ints[] = new Integer[] {1,2,3};
messUp(ints);

这会在没有警告的情况下编译,但在执行时会引发ArrayStoreException。

要回答您的问题,请列出

这不构成列表

<T extends Exception> void foo(List<T> exceptions) { 
    List<Exception> l = exceptions;
    l.add(new RuntimeException());       
}

但这不会编译,因为

宋洲
2023-03-14

我认为你的问题的简单答案是语义上的
<代码>列表

换一种说法:

 Object[] array = new String[2]; //is a valid declaration.
 List<Object> list = new ArrayList<String>(); //is not. 
李甫
2023-03-14

<代码>列表

这意味着列表可以采用异常的子类型

不完全是。您可以将一个列表或其任何子类型分配给k,在这种情况下,可以将异常的任何子类型分配给k。

但是您不能将异常的任何子类型或任何相关内容添加到k,因为k是异常的一些未知子类型的列表。例如

k.add(new NumberFormatException());

将给出一个错误。

检索也仅限于已知类型:

NumberFormatException e1 = k.get(0); // error
Exception e2 = k.get(0); // ok, anything in k must be an Exception
NumberFormatException e3 = (NumberFormatException) k.get(0); // ok, but the usual downcast issues exist
 类似资料:
  • 在爪哇,its说: 所以数组被称为协变的。但对于泛型,他们说: 因此它是不变的。但问题是,“泛型真的是不变的吗”? 那为什么说泛型是不变的呢?

  • 问题内容: 我想知道Java中是否有特殊原因总是使用“ ”而不是“ ”来定义类型参数的界限。 例: 被禁止但是 是正确的。是什么原因呢? 问题答案: 在类“实现”还是“扩展”之间,通用约束语言没有语义差异。约束可能性是“扩展”和“超级”-也就是说,该类是可分配给其他类的对象(扩展),还是该类可从该类分配(超级)。

  • 问题内容: 作为实验,我尝试扩展-array,如下所示: 在类本身中添加一些与排序,交换,子数组构建等有关的方法。但是我在编译时遇到了这个错误: 我很好奇:为什么Java不允许扩展数组? 问题答案: 扩展基本类型(例如a 或数组)会打开安全漏洞。如果Java允许您扩展数组,则采用数组的方法将变得不安全。这就是字符串为,而数组根本不能扩展的原因。 例如,您可以重写该方法,并返回不正确大小的数组。这有

  • 下面的泛型代码无法编译,我可以理解原因:这是为了阻止可能不兼容的类型添加到集合中: 然而,我可以对数组做同样的事情,并且不会得到编译器错误。当我运行它时,我会得到一个 为什么编译器不阻止我上传数组,因为它会麻烦地阻止我上传泛型?

  • 问题内容: 这是我一直试图找到解决方案的问题。 我们有两个类定义。两个之一扩展另一个。 要求是应该有一个列表来保持对象扩展T 但是,当我尝试将TT对象(似乎不是T的子类)放入列表时,就会出现问题。 编译错误信息 类型List中的方法add(capture#2-of?extended Cell)不适用于参数(Cell) 问题答案: 您可以直接创建一个,这可以允许T的所有子类型进入列表。这实际上很难理

  • 从Joshua Bloch的Effective Java中, > 数组与泛型类型有两个重要的区别。第一个数组是协变的。泛型是不变的。 协变简单地说,如果X是Y的子型,那么X[]也将是Y[]的子型。数组是协变的,因为字符串是对象的子类型,所以 不变简单地说,不管X是不是Y的子类型, 我的问题是为什么决定在Java中使数组是协变的?还有其他的SO帖子,比如为什么数组是不变的,但是列表是协变的?,但它们