10
  1. エラーなし

    Object[] a = new String[]{"12","34","56"};
    String[] b = (String[]) a;
    
  2. エラーなし

    Object a = new String[]{"12","34","56"};    
    String[] b = (String[]) a;
    
  3. 実行時エラー: ClassCastException

    Object[] a = new Object[3];
    a[0] = "12";
    a[1] = "34";
    a[2] = "56";
    String[] b = (String[]) a;
    
  4. 実行時エラー: ClassCastException

    Object[] a = {"12","34","56"};    
    String[] b = (String[]) a;
    

もちろん、Object[]変数String[]String[].

Object[]私の質問は、作成されたString[]ときにキャストできないObject[]のに、そのすべてのメンバーが文字列であるのはなぜですか? セキュリティ上の理由によるものですか、それともこれを実装するのはそれほど役に立ちませんか?

4

6 に答える 6

8

考えられる理由は2つあります。

まず、元の配列を変更すると、キャストされた配列が無効になる可能性があります。例えば

 Object[] a = {"12","34","56"};   
 String[] b = (String[]) a; // pretend this is legal. a and b now point to the same array

 a[0] = new Object(); // clearly ok
 String x = b[0]; // No longer a string! Bad things will happen!

第 2 に、選択した例は非常に単純ですが、非常に大きなObject[]配列があり、それを埋めているものがコンパイラに明確でない場合、配列のすべての要素がキャストを満たしていることを検証する方法がありません。

Object[] a = new Object[10000];
// lots of weird and whacky code to fill the array with strings

String[] b= (String[]) a; // valid or no? The best-defined answer is to say no.
于 2013-08-08T06:57:33.783 に答える
5

JLS #5.5.3で定義されています。実際には、キャスト:

 r = new RC[]; TC[] t = (TC[]) r;

RC が TC (または TC 自体) のサブタイプである場合、実行時に「動作」します。RC に実際に TC のみが含まれているかどうかは無関係であり、r のコンパイル時の型も使用されません (重要なのは実行時の型です)。

  • あなたは書くことができますr = new String[]; Object[] t = (Object[]) r;
  • あなたは書くことができませんr = new Object[]; String[] t = (String[]) r;

JLS の抜粋:

T が配列型 TC[]、つまり、型 TC のコンポーネントの配列である場合、次のいずれかが true でない限り、実行時例外がスローされます。

  • TC と RC は同じプリミティブ型です。
  • TC と RC は参照型であり、RC 型は、これらの実行時のキャスト規則を再帰的に適用することで TC にキャストできます。

例 3 および 4 では、RC = オブジェクトおよび TC = 文字列であり、オブジェクトは文字列のサブタイプではありません。例 1 と 2 では、RC = 文字列と TC = 文字列なので、機能します。

注: このコンテキストの型はランタイム型です。

于 2013-08-08T06:52:25.593 に答える
3

配列の個々のメンバーをキャストしていないため、型ではなく配列インスタンス全体をキャストしています。Object[]String[]

Object[] a = new String[]{"12","34","56"};

ここで、インスタンスの型はString[]で、コンパイル時の型はObject[]です。

String[]次の行では、実際の型またはランタイム型として許可されているものにキャストし直していますString[]

しかし、Object[] a = new Object[3];ここでは実際の型とコンパイル時の型はObject[]であり、そうではありませんString[]。したがって、は でObject[]はありませんString[]

Object[] a = new Object[1];
a[0] = "a"; //Actual type String 

だからあなたはこれを行うことができます:

String aStr = (String)a[0];
于 2013-08-08T06:48:29.057 に答える
2

配列オブジェクトは単に要素のコレクションではなく、他のオブジェクトと同様にクラスを持ちます。文字列配列のクラスは、オブジェクト配列のサブクラスです。そのため、1 または 2 にエラーはありませんが、最後の 2 つは同等です

Object o = new Object();
String s = (String) o;
于 2013-08-08T06:50:42.550 に答える
2

キャストの時点でオブジェクト配列のすべてのメンバーが文字列だった場合でも、後でこの配列の要素に文字列ではないオブジェクトを割り当てることができます。したがって、文字列ではない要素を持つ文字列配列があります。

于 2013-08-08T06:52:36.757 に答える