簡體   English   中英

如何將Object數組轉換為整數數組數組

[英]How can I cast an Object array to an array of arrays of integers

這是一個人為的例子,可以解決我遇到的情況,但基本上,我有一個對象數組,實際上包含整數數組,我正在嘗試這樣做。 這是一個模擬這種情況的代碼片段:

Object[] foo = new Object[3];
foo[0] = new int[] { 1, 2, 3 };
foo[1] = new int[] { 4, 5, 6 };
foo[2] = new int[] { 7, 8, 9 };
int[][] bar = (int[][]) foo;

當我嘗試這樣做時,我Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[I得到異常Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[I Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[I

有沒有辦法在不復制數組的情況下執行此操作(我可能不想這樣做,因為foo在生產中會非常大)? 如果沒有,為什么不呢?

您不能通過強制轉換來更改Java對象的內部類型。 這包括數組。 對象的類型在分配對象時是固定的,不能更改。

因此將Object[]int[][]將永遠不會起作用。

在這種情況下,雖然int[][]Object[]的子類型,但這不足以在運行時允許類型轉換。 JLS中的實際規則( 5.5.3。運行時檢查的轉換 )是這樣的:

“這是用於檢查對象的運行時類型R是否與類型T兼容的算法,類型T是在轉換運算符中指定的類型的擦除(第4.6節)。如果拋出運行時異常,這是一個ClassCastException 。“ ...

“如果R是表示數組類型RC []的類,即RC類型的組件數組:

  • “如果T是數組類型TC [],即TC類型的組件數組,則拋出運行時異常,除非滿足以下條件之一:”

    • “TC和RC是相同的原始類型。”

    • “TC和RC是引用類型,類型RC可以通過遞歸應用這些運行時規則來轉換為TC。”

在這種情況下,TC是int[] ,RC是ObjectObject 不能轉換int[] 因此你得到一個例外。

為了說明為什么必須發生這種情況,請考慮這個(假設的)示例:

   Object[] foo = new Object[3];
   foo[0] = new Object();
   int[][] bar = /* foo */
   int[] mystery = bar[0];

假設有可能“投射” foo的值,那么mystery變量應該指向什么? 它不能是int[]因為我們沒有分配一個。 它不能是Object實例,因為這會破壞靜態類型。

事實上,“演員”必須是非法的,否則Java的靜態類型系統就會崩潰。


你和我的例子之間的區別在於foo實際上並不是整數數組的數組,而在我的情況下則是。 為什么VM無法看到對象的“實際”類型?

關鍵是靜態類型(主要)由編譯器強制執行,而不是由JVM強制執行。 雖然JVM可以(在理論上)計算出該類型是在運行時確定(並拋出異常,如果他們都沒有),編譯器不能做到這一點,因為它不是一般的判斷是什么類型的都將是。


不幸的是,我實際上並沒有自己創建陣列。 我從另一個函數得到它而且,就我所知, Object[]而不是int[][]是我無法控制的某些序列化的副作用。

不幸的是,您必須復制數組...或將其用作Object[]並將元素轉換為int[]以使用它們; 例如

Object[] foo = new Object[3];
foo[0] = new int[] { 1, 2, 3 };
foo[1] = new int[] { 4, 5, 6 };
foo[2] = new int[] { 7, 8, 9 };
...
int nine = ((int[]) (foo[2]))[2];

Java中沒有“相信我它真的是一個int[][] ”選項。

如果這是序列化的副作用,那么在某種意義上序列化就會被打破。 當然,標准Java對象序列化協議/實現不會發生這種情況。 保留了對象的類型......除非你在readObject / writeObject方法中顯式地覆蓋它們,等等。

因為foo是對象數組,所以它意味着它可以包含任何東西,而不僅僅是整數數組,所以編譯器不允許你將它轉換為整數數組,因為你知道它在里面。

如果要使用int[][] bar引用,則必須首先創建單獨的int [3][]數組,並將foo內容復制到該數組。

您需要在訪問時轉換每個對象。

    Object[] foo = new Object[3];
    foo[0] = new int[] { 1, 2, 3 };
    foo[1] = new int[] { 4, 5, 6 };
    foo[2] = new int[] { 7, 8, 9 };
    int[] foo2 = (int[])foo[2];
    System.out.println("foo[2,2]="+((int[])foo[2])[2]);

如果您認為內容可能是非整數的話,您也應該將它包裝在try ... catch

編輯:簡化代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM