繁体   English   中英

为什么我不能将对象数组转换为通用 class 的通用子类的数组?

[英]Why can't I cast an array of Objects to an array of a generic subclass of a generic class?

此代码有效。 它编译并运行时会出现“未经检查或不安全的操作”警告。

class Foo<T> {
  T[] items = (T[]) new Object[10];

  public static void main(String[] args) {
    Foo<Integer> foo = new Foo<Integer>();
  }
}

虽然这两个给了我运行时错误

class Foo<T> {
  class FooItem { T item; }

  FooItem[] items = (FooItem[]) new Object[10];

  public static void main(String[] args) {
    Foo<Integer> foo = new Foo<Integer>();
  }
}
class Foo<T> {
  static class FooItem<E> { E item; }

  FooItem<T>[] items = (FooItem<T>[]) new Object[10];

  public static void main(String[] args) {
    Foo<Integer> foo = new Foo<Integer>();
  }
}

我遇到的错误如下:

线程“主”中的异常 java.lang.ClassCastException: class [Ljava.lang.Object; 不能转换为 class [LFoo$FooItem; ([Ljava.lang.Object; is in module java.base of loader 'bootstrap'; [LFoo$FooItem; is in unnamed module of loader com.sun.tools.javac.launcher.Main$MemoryClassLoader

为什么是这样?

您的Foo class 的所有版本都有同样的问题。 Type safety: Unchecked cast from Object[] to X警告您忽略的只是在执行期间的不同阶段显示其后果。

这是破坏您的第一个版本的方法:

class Foo<T> {
    T[] items = (T[]) new Object[10];

    public static void main(String[] args) {
        Foo<Integer> foo = new Foo<Integer>();

        Integer i = foo.items[1] * 2;
    }
}

它崩溃了......同样的问题:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
    at stackoverflow.Foo.main(Main.java:17)

为什么? 因为(T[]) new Object[10]; 在编译时不强制执行,即编译器不知道如何验证T[]Object[]之间的关系

就像您不能将new Object()转换为Integer ,您也不能将new Object[10]转换为Integer[] 只是这个 class 转换异常仅在运行实际转换时出现。 对于第一个片段,它不在声明语句上运行, T[] items = (T[]) new Object[10]; (因此警告),但是当items用作T的类型参数时。

您的其他版本会更快地显示问题,因为它们正在转换为具体类型,例如(FooItem[]) new Object[10] ,导致声明语句本身崩溃。
为什么编译器允许这种转换? 因为类型关系是有效的,给定这样的代码

Object[] items = new Integer[10];
Integer[] i = (Integer[])items;
Integer val = i[0];

有效且受支持。

不能将Object[]转换为T[]的原因是这可能会导致以下代码出现问题:

Object[] objects = new Object[10];         // This is fine
objects[0] = "Hello World";                // Is fine since String is subtype of Object
T[] ts = (T[]) objects;                    // One could argue that this is fine
T firstT = ts[0];                          // Now we have the issue that String needs to be casted to T

因此,不允许将Object[]转换为T[] generics 类似列表的情况也是如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM