为了账号安全,请及时绑定邮箱和手机立即绑定

为什么数组是协变的,但是泛型是不变的?

为什么数组是协变的,但是泛型是不变的?

一只甜甜圈 2019-06-19 17:34:43
为什么数组是协变的,但是泛型是不变的?来自约书亚·布洛赫的有效Java,数组与泛型类型有两种重要的区别。首先,数组是协变的。泛型是不变的。协变简单地表示,如果X是Y的子类型,那么X[]也将是Y[]的子类型。数组是协变量的,因为字符串是对象的子类型,所以String[] is subtype of Object[]不变的意思是不管X是不是Y的子类型, List<X> will not be subType of List<Y>.我的问题是,为什么决定在Java中使数组协变?还有其他这样的帖子,比如为什么数组是不变的,但是列表是协变量的呢?,但他们似乎专注于Scala,我无法理解。
查看完整描述

3 回答

?
莫回无

TA贡献1865条经验 获得超7个赞

原因是每个数组在运行时都知道其元素类型,而泛型集合不知道类型擦除。

例如:

String[] strings = new String[2];Object[] objects = strings;  // valid, String[] is Object[]objects[0] = 12;
 // error, would cause java.lang.ArrayStoreException: java.lang.Integer during runtime

如果泛型集合允许这样做:

List<String> strings = new ArrayList<String>();List<Object> objects = strings;  // let's say it is validobjects.add(12);  
// invalid, Integer should not be put into List<String> but there is no information during runtime to catch this

但是,当有人试图访问列表时,这会引起问题:

String first = strings.get(0); // would cause ClassCastException, trying to assign 12 to String


查看完整回答
反对 回复 2019-06-19
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

可能是这,这个帮助:-

泛型不是协变的

Java语言中的数组是协变的-这意味着如果Integer扩展了数字(它确实是这样做的),那么不仅是整数也是数字,而且Integer[]也是一个Number[],您可以自由地传递或分配Integer[]其中一个Number[]被要求。(更正式地说,如果数字是整数的超级类型,那么Number[]Integer[])您可能会认为泛型类型也是如此。List<Number>List<Integer>,你可以通过一个List<Integer>其中一个List<Number>都是意料之中的。不幸的是,它不是那样工作的。

事实证明,这是有一个很好的理由,它不工作的方式:它将打破类型的安全泛型本应提供的。假设您可以分配一个List<Integer>转到List<Number>..然后,下面的代码将允许您将非Integer的内容放入List<Integer>:

List<Integer> li = new ArrayList<Integer>();List<Number> ln = li; // illegalln.add(new Float(3.1415));

因为ln是一个List<Number>给它添加一个浮动似乎是完全合法的。但如果我和li,然后它将打破类型安全承诺,这是一个整数列表,这就是为什么泛型类型不能是协变的。


查看完整回答
反对 回复 2019-06-19
  • 3 回答
  • 0 关注
  • 813 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信