【问题标题】:Why does a type conversion not work in Java [duplicate]为什么类型转换在 Java 中不起作用 [重复]
【发布时间】:2014-01-23 07:22:13
【问题描述】:

我想知道为什么这种转换不起作用:

ArrayList<Song> arrayList =new ArrayList<MediaItem>();

我可能需要补充一点,即 Song 扩展了 MediaItem。 我认为这种转换应该有效,因为 Song 能够存储 MediaItem 中的所有信息。所以不会丢失任何信息。 有人给我解释一下吗?

【问题讨论】:

标签: java generics arraylist casting covariance


【解决方案1】:

有人给我解释一下吗?

如果该分配有效,那么您可以将Song 的另一个子类的实例(与MediaItem 完全无关)放入列表中。因此是不允许的。换句话说,Java 泛型不是covariant

【讨论】:

    【解决方案2】:

    这不起作用,因为 Java 中的泛型不是协变的。也就是说,List&lt;Song&gt;List&lt;MediaType&gt; 是两个完全不相关的类型,尽管 SongMediaType 是相关的。

    【讨论】:

      【解决方案3】:

      这是矛盾的。一方面,声明了Songs 的ArrayList,因此Songs 和派生自Song 的类的对象可以存储在那里。但是,new ArrayList&lt;MediaItem&gt;() 正在创建派生类型的 ArrayList,这意味着直接从 Song 派生的其他对象无法存储。类型之间的差异是不可调和的。

      【讨论】:

        【解决方案4】:

        这是因为 Java 中的泛型类型没有协变/逆变。如果你能像那样做作业,你就能做到:

        ArrayList<MediaItem> mediaItems = new ArrayList<MediaItem>(); // Legal
        ArrayList<Song> songs = mediaItems; // Illegal; let's imagine it's legal for a moment
        // Note that songs and mediaItems are the same list
        songs.add(new Song());         // This is perfectly fine
        Song firstSong = songs.get(0); // That's OK - it's a Song
        mediaItems.add(new Video());   // This is perfectly fine, too
        // However, the addition above also modifies songs: remember, it's the same list.
        // Now let's get the last object from songs
        Song lastSong = songs.get(1);  // Wait, that's not a Song, it's a Video!!!
        

        Java 不希望这种情况发生。因此,它禁止将基于子类的泛型类型分配给基于相应基类的泛型类型。

        【讨论】:

        • 你确定你的第一行是合法的吗?两边不应该是MediaItem吗
        • @RichardTingle 绝对,你是 100% 正确的!这是一个复制粘贴错误。当您看到这样的直截了当的错误时,请随时进行编辑。非常感谢!
        【解决方案5】:

        你的ArrayLists 有不同的具体参数化类型

        GenericTypes.FAQ101了解更多信息

        泛型类型的实例化,其中所有类型参数都是具体类型而不是通配符。 具体参数化类型的示例是List&lt;String&gt;Map&lt;String,Date&gt;,但不是List&lt;? extends Number&gt;Map&lt;String,?&gt;

        Arrays in Java Generics - What are the issues regarding arrays in Java Generics?

        泛型集合不是协变的。超类型的参数化类型的实例化不被视为子类型的相同参数化类型的实例化的超类型。也就是说,LinkedList&lt;Object&gt; 不是LinkedList&lt;String&gt; 的超类型,因此LinkedList&lt;String&gt; 不能用于需要LinkedList&lt;Object&gt; 的地方;这两个具有相同参数化类型的实例之间没有赋值兼容性,等等。

        这是一个说明差异的示例:

        LinkedList&lt;Object&gt; objLst = new LinkedList&lt;String&gt;(); // compile-time error

        您可以通过擦除参数化类型和强制转换来实现这一点:

        ArrayList<Song> arrayList = (ArrayList<Song>) (ArrayList<?>) new ArrayList<MediaItem>();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-11-20
          • 2019-12-04
          • 2016-02-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-02
          相关资源
          最近更新 更多