ジェネリック医薬品、配列の場合は、ClassCastExceptionが
-
21-08-2019 - |
質問
いきものが微妙にちいないわからない。以下を考えます:
public class Foo<T> {
private T[] a = (T[]) new Object[5];
public Foo() {
// Add some elements to a
}
public T[] getA() {
return a;
}
}
しかし本法の内容は次のとおりです。
Foo<Double> f = new Foo<Double>();
Double[] d = f.getA();
を取得しま CastClassException
メッセージ java.lang.Object
できないキャスト java.lang.Double
.
誰でもできるので教えてなぜですか?私の理解 ClassCastException
この場合にスローされます試しキャストへのオブジェクト種類できない鋳.それは、クラスのサブクラスではインスタンス(引用文書).例えば:
Object o = new Double(3.);
Double d = (Double) o; // Working cast
String s = (String) o; // ClassCastException
るようになったようできません。の場合 a
ただ T
の代わりに配列 T[]
, かむことができま a
キャストな問題です。なぜ配列の休憩。
感謝。
解決
Foo<Double> f = new Foo<Double>();
ご利用の際はこのバージョンの汎用クラスFooのメンバ変数 a
, のコンパイラはこのライン:
private T[] a = (T[]) new Object[5];
交換 T
と Double
この:
private Double[] a = (Double[]) new Object[5];
できなキャストからオブジェクトをダブル、そのため、ClassCastException.
更新の解明: 実際には、走行テストコードの場合は、ClassCastExceptionがより繊細なります。例えば、この方式が主流に作な例外:
public static void main(String[] args) {
Foo<Double> f = new Foo<Double>();
System.out.println(f.getA());
}
の問題が発生しないように割り当て f.getA()
参考タイプ Double[]
:
public static void main(String[] args) {
Foo<Double> f = new Foo<Double>();
Double[] a2 = f.getA(); // throws ClassCastException
System.out.println(a2);
}
このタイプに関する情報はメンバ変数 a
は消去を行います。ジェネリック医薬品を型安全 コンパイル時の ったのかを無視してこれを最初にしました。でも問題ありません
private T[] a = (T[]) new Object[5];
が実行時にこのコードは本当に
private Object[] a = new Object[5];
万一問題が発生した場合の方法 getA()
, は、実行時に実際に返されます Object[]
, を配置して、参照の型 Double[]
-この文の投ClassCastExceptionがオブジェクトなキャストしまいます。
更新2:お答えし最終のものに"なぜアレイの休憩。 その答えは、言語仕様は一般配列。 このフォーラムポスト用 -するための下位互換性はなにもわかっていないタイプのプリケーションに合うかどうかを行います。
他のヒント
の@ mattbの説明では、いくつかの小さな誤差がある場合があります。
エラーがあるのないの
java.lang.Objectのは、java.lang.Doubleのにキャストすることはできません。
これは、次のとおりです。
[Ljava.lang.Object。 [Ljava.lang.Double
にキャストすることはできません
[Lは配列を意味します。これは、エラーがオブジェクトのの列はダブルの配列にキャストできないということで、あります。これは、次のように同じケースです。
Object[] oarr = new Object[10];
Double[] darr = (Double[]) oarr;
これは明らかに許可されていません。
タイプセーフ配列を作成するあなたの問題のために、別の代替は、initでクラスオブジェクトを除き、またArray.newInstanceを使用することです。
import java.lang.reflect.Array;
class Foo<T> {
private T[] a ;
public Foo(Class<T> tclass) {
a = (T[]) Array.newInstance(tclass, 5);
}
public T[] getA() {
return a;
}
public static <T> Foo<T> create(Class<T> tclass) {
return new Foo<T>(tclass);
}
}
class Array1
{
public static final void main(final String[] args) {
Foo<Double> f = Foo.create(Double.class);
Double[] d = f.getA();
}
}
@mattのB:答えてくれてありがとう!非常に役に立っています。
下駄メソッドに移入するように初期化配列を与える:私が興味のある人のための回避策を発見しました。その方法は、型情報が提供されてます。
public class Foo<T> {
private T[] a = (T[]) new Object[5];
public Foo() {
// Add some elements to a
}
public T[] getA(T[] holdA) {
// Check whether holdA is null and handle it...then:
holdA = (T[]) Array.newInstance(holdA.getClass().getComponentType(), a.length);
System.arraycopy(a, 0, holdA, 0, a.length);
return holdA;
}
}
次に、あなたの主な方法についてます:
public static void main(String[] args) {
Foo<Double> f = new Foo<Double>();
Double[] a2 = new Double[1];
a2 = f.getA(a2);
}