2

重複の可能性:
Java で汎用配列を作成する

オブジェクトの汎用配列を最初の len 要素のみにトリミングしたいと考えています。これはうまくいくようです:

@SuppressWarnings("unchecked")
public static <T> T[] trimArray(T[] data, int len){
    T[] result = (T[]) new Object[len];
    System.arraycopy(data, 0, result, 0, len);
    return result;
}

しかし、次のようなことをすると ClassCastException がスローされます

public class Foo{

    double f;

    public Foo(double f){
    this.f = f;
    }

}

public static void main(String[] args){

    Foo[] A = new Foo[10];
    A[0]= new Foo(1);
    A[1]= new Foo(2);
    A[2]= new Foo(3);
    Foo[] B = trimArray(A, 3);

}

なぜこれがうまくいかないのか理解できませんが、ジェネリッククラスのJavaジェネリックキャストでも同様のことが起こります

4

2 に答える 2

11

JDKにはすでにこのための組み込みがあります。

Foo[] B = Arrays.copyOf(A, 3);

Javadoc(1.6以降)

ただし、ソース配列の長さが必要な長さよりも短い場合は、配列も拡張されることに注意してください(sが埋め込まれます)。nullたとえば、次を使用してこれを簡単に回避できます。

Foo[] B = Arrays.copyOf(A, Math.min(3, A.length));
于 2012-12-30T17:56:49.917 に答える
1

これは、配列が共変であるために発生します。つまり、サブタイプの配列をスーパータイプの配列として自由に扱うことができますが、その逆は当てはまりません。

醜いハックですが、必要に応じて、を返し、各要素Object[]をキャストしますT(配列内の実際の要素は共変ですが、配列自体はそうではありません)が、強くお勧めします。

のような別の回答で推奨されているビルトインを使用してくださいArrays.copyOf

なぜだろうと思っているのなら、これは型安全性を簡単に壊してしまうからです。

例えば:

Object[] bla = new Object[10];
bla[0] = new Integer(2);
bla[1] = "stillanObject";

完全に有効なオブジェクトの配列があります。

これで、たとえば、文字列の配列にキャストします...

return (String[])bla;

そして、地獄はJVMで解き放たれます、あなたは実際にオブジェクトを含むタイプでなければならない配列を持っているでしょうString!\StringInteger

型安全性は良いことです。

アップデート:

もう1つ詳細を追加するために、にキャストできますがString[]、(または元の配列のタイプ)以外のものを格納しようとするとObject[]、が発生する可能性があります。ただし、元の配列を完全に安全に読み取ることができます。ArrayStoreExceptionStringObject[]

于 2012-12-30T18:01:58.763 に答える