キャストによって Java オブジェクトの組み込み型を変更することはできません。これには配列が含まれます。オブジェクトのタイプは、オブジェクトが割り当てられるときに固定され、変更できません。
Object[]
したがって、 toのキャストは機能しint[][]
ません。
この場合、 whileint[][]
は のサブタイプですがObject[]
、実行時に型キャストを許可するにはこれでは不十分です。JLS ( 5.5.3. Checked Casts at Run Time ) の実際のルールは次のとおりです。
「オブジェクトの実行時型 R が、キャスト演算子で指定された型の消去 (§4.6) である型 T と互換性のある代入であるかどうかをチェックするアルゴリズムは次のとおりです。実行時例外がスローされた場合、ですClassCastException
。」...
「R が配列型 RC[] を表すクラス、つまり、型 RC のコンポーネントの配列である場合:」
この場合、TC はint[]
RC でObject
あり、にキャストするObject
ことはできません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 は (理論的には) 実行時に型が OK であることを判断できます (そうでない場合は例外をスローします) が、コンパイラは一般に型がどうなるかを判断できないため、これを行うことができません。
残念ながら、私は実際に自分で配列を作成していません。私は別の関数からそれを取得していますが、私が知る限り、それは私が制御できないシリアライゼーションの副作用です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