簡體   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