4

こんにちは、以下のコードを確認してください

   ArrayList x=new ArrayList();
   ArrayList<String>y=x;
   ArrayList<StringBuffer>z=x;
   y.add("Strings");
   System.out.println(z.get(0).toString());

System.out.println で Class Cast Exception が発生しています

 java.lang.ClassCastException: java.lang.String
 at com.one.MainClass.main(MainClass.java:16)

しかし、私がしようとしているとき

  System.out.println(z.get(0)) 

なぜこれが来るのですか??

4

2 に答える 2

2

実験としてそれを行っていると思います(そうでない場合は、コードをどのように書くべきかについて他の回答を読んでください)。

x は rawArrayListであり、任意のタイプのオブジェクトを配置できます。

y.add("string")文字列を追加します。

z は でありArrayList<StringBuffer>、StringBuffer が必要です。を呼び出すz.get(0)と、JVM はインデックス 0 の要素を返す前に StringBuffer にキャストしようとします。そのキャストは失敗します。

つまり、コンパイルはされますがStringBuffer s = z.get(0);、実行時に ClassCastException がスローされます。z.get(0)StringBuffer

于 2012-08-05T15:49:00.017 に答える
1

問題が発生する理由の詳細は次のとおりです。

  • 新しい ArrayList が作成され、空です
  • すべての要素は y の String に型指定されます
  • すべての要素は z の StringBuffer に型指定されます
  • この配列リストに新しい要素が追加されます。
  • JVM はそれを String と StringBuffer の両方にキャストしようとします。
  • 「Strings」は StringBuffer のインスタンスではないため、ClassCastException がスローされます。

これを回避するには、String と StringBuffer の両方に型指定された配列を持たないようにします。1 つだけ選択します。例えば:

ArrayList<StringBuffer> myArrayList = new ArrayList<StringBuffer>

String 配列リストを StringBuffer ArrayList にコピーする場合は、z 内のすべての項目を反復処理して、それらを文字列バッファーに変換する必要があります。

ArrayList x=new ArrayList();
ArrayList<String>y=x;
ArrayList<StringBuffer>z=new ArrayList<StringBuffer>();
for(String s : y)
    z.add(new StringBuffer(s));

これは、StringBuffer が String を拡張しないためです。問題の原因は、文字列をキャストできないことです。たとえば、「str」を StringBuffer にキャストすることはできませんStringBuffer s = (StringBuffer)"str";

にキャストArrayList xするにArrayList<T>は、 のすべての要素xが拡張されているか、 のインスタンスである必要がありますT

さらに、可能であれば、常にジェネリック型を使用する必要があります。(たとえば) リストに何が表示されるかわからない場合は、次を使用します。

ArrayList<?> x = new ArrayList<?>();

別のクラスのサブクラスになるなど、もう少しわかっている場合は、 ArrayList<? extends T>またはを使用しますArrayList<? implements T>。これにより、将来の ClassCastExceptions を回避できます。

于 2012-08-05T15:43:07.530 に答える