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

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

来自约书亚·布洛赫的有效Java,

  1. 数组与泛型类型有两种重要的区别。首先,数组是协变的。泛型是不变的。
  2. 协变简单地表示,如果X是Y的子类型,那么X[]也将是Y[]的子类型。数组是协变量的,因为字符串是对象的子类型,所以

    String[] is subtype of Object[]

    不变的意思是不管X是不是Y的子类型,

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

我的问题是,为什么决定在Java中使数组协变?还有其他这样的帖子,比如为什么数组是不变的,但是列表是协变量的呢?,但他们似乎专注于Scala,我无法理解。


一只甜甜圈
浏览 817回答 3
3回答

莫回无

原因是每个数组在运行时都知道其元素类型,而泛型集合不知道类型擦除。例如:String[]&nbsp;strings&nbsp;=&nbsp;new&nbsp;String[2];Object[]&nbsp;objects&nbsp;=&nbsp;strings;&nbsp;&nbsp;//&nbsp;valid,&nbsp;String[]&nbsp;is&nbsp;Object[]objects[0]&nbsp;=&nbsp;12; &nbsp;//&nbsp;error,&nbsp;would&nbsp;cause&nbsp;java.lang.ArrayStoreException:&nbsp;java.lang.Integer&nbsp;during&nbsp;runtime如果泛型集合允许这样做:List<String>&nbsp;strings&nbsp;=&nbsp;new&nbsp;ArrayList<String>();List<Object>&nbsp;objects&nbsp;=&nbsp;strings;&nbsp;&nbsp;//&nbsp;let's&nbsp;say&nbsp;it&nbsp;is&nbsp;validobjects.add(12);&nbsp;&nbsp; //&nbsp;invalid,&nbsp;Integer&nbsp;should&nbsp;not&nbsp;be&nbsp;put&nbsp;into&nbsp;List<String>&nbsp;but&nbsp;there&nbsp;is&nbsp;no&nbsp;information&nbsp;during&nbsp;runtime&nbsp;to&nbsp;catch&nbsp;this但是,当有人试图访问列表时,这会引起问题:String&nbsp;first&nbsp;=&nbsp;strings.get(0);&nbsp;//&nbsp;would&nbsp;cause&nbsp;ClassCastException,&nbsp;trying&nbsp;to&nbsp;assign&nbsp;12&nbsp;to&nbsp;String

慕桂英546537

可能是这,这个帮助:-泛型不是协变的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>&nbsp;li&nbsp;=&nbsp;new&nbsp;ArrayList<Integer>();List<Number>&nbsp;ln&nbsp;=&nbsp;li;&nbsp;//&nbsp;illegalln.add(new&nbsp;Float(3.1415));因为ln是一个List<Number>给它添加一个浮动似乎是完全合法的。但如果我和li,然后它将打破类型安全承诺,这是一个整数列表,这就是为什么泛型类型不能是协变的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java