2015-12-24 7 views
7

コードを実行するときに暗黙的にdをdoubleにキャストするため、これを実行するとClassCastExceptionエラーが発生します。しかし、もしdへの参照をObject[]に変更すると、それはset関数のパラメータになることはできません。 Object[]を受け入れるようにset関数を変更すると、すべて正常に動作しますが、タイプがNでないオブジェクトに対してsetを呼び出すと、実行時にクラスが失敗します。汎用クラスから配列を返す

私は、古い配列(またはそのクローン)をget()とすることができ、新しい配列にset()データを入れることができる解決策が必要です。

public class Foo<N> { 

    public static void main(String[] args) { 
     Foo<Double> foo = new Foo<Double>(); 
     Double[] d = foo.get(); 

     // do stuff to d ... 

     foo.set(d); 
    } 

    N[] data; 

    public Foo() { 
     data = (N[]) new Object[2]; 
    } 

    public N[] get() { 
     return (N[]) data; 
    } 

    public void set(N[] data) { 
     this.data = data; 
    } 

} 
+1

[Javaで汎用配列を作成するにはどうすればいいですか?](http://stackoverflow.com/questions/529085/how-to-create-a-generic-array-in-java) – Julien

+0

そのqの複製。 – avisnacks

+0

このhttp:// stackoverflowを使用することができます。com/a/3403976/2513573型を抽出し、Array.newInstanceを使って配列を作成する – AdamSkywalker

答えて

1

正しいランタイムタイプの配列を作成するには、そのタイプのランタイム表現が必要です。 Foo<N>のような汎用クラスには、実行時表現Nがありません。

  1. ではなくList<N>を使用してください:

    は、二つの解決策があります。これが可能なら最高です!

  2. Class<N>Fooを渡してランタイム表現Nを手動で追加するには、java.lang.reflect.Array.newInstanceを使用して配列を作成します。第二の溶液のための

コード:

public Foo(Class<N> newDataClass) { 
    data = (N[]) Array.newInstance(newDataClass, 2); 
} 

Foo<Double> foo = new Foo<>(Double.class); 

EDIT:

何がやりたいことは、あなたが行うことができ、既存のDouble配列のコピーを取得する代わりにある場合それは(N[]) data.clone()である。それを設定することは問題ではありません。

1

これにはトリックがあります。

class Foo<N> { 

    // Deliberately no parameters. 
    N[] myArray = makeArray(); 

    private N[] makeArray(N... ns) { 
     return ns; 
    } 

    public N[] get() { 
     return myArray; 
    } 
} 

これは(良いことです)は、鋳造がないように見えるが、実際にそれがちょうどvarargsシステムによって行われている、そこにあることがあります。

+0

多分私は疑問に思っていませんでしたが、私の場合は配列がすでにインスタンス化されていて、変更する必要があります。だから私はfooからそれを得る必要があります。それをリセットします。私は、それをコンストラクタでインスタンス化するソリューションを持つことはできません。 – avisnacks

+2

@avisnacks:あなたの例では、 'Foo'コンストラクタで配列を作成します。それはどのように働くべきではありませんか?それをもっと明確にするために質問を更新できますか? – Lii

+0

@OldCurmudgeon:これは動作しません。あなたは常に 'myArray'に' Object'配列を取得します。初期化子が 'makeArray'を呼び出すとき、' N'のトレースは残っておらず、消去されています。一般的なvarargメソッドは常に 'Object'配列を作成します。ジェネリック型の配列はまったく作成できません。これは、たとえば、[Javaチュートリアル](https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createArrays)に記載されています。 – Lii

1

便利な(しかし冗長な)方法は、メインのメソッドで2倍であることがわかっているので、コンストラクタを配列型で仮引数を取るように変更することです。

public class Foo<N> { 
     N[] data; 

     public Foo(N inType) { 
      data = (N[]) Array.newInstance(inType.getClass(), 2) ; 
     } 

     public N[] get() { 
      return (N[]) data; 
     } 

     public void set(N[] data) { 
      this.data = data; 
     } 

     public static void main(String[] args) { 
      Foo<Double> foo = new Foo<Double>(new Double(0)); 
      Double[] d = foo.get(); 
      // do stuff to d ... 
      foo.set(d); 
     } 

    } 
0

一般的な問題は、実行時に特定のタイプがないことです。実際には、タイプObjectのオブジェクトを作成するだけなので、そのようなオブジェクトを作成することは全く意味がありません。つまり、クラスObjectです。

ただし、オブジェクトの実際の型がここにわかっているので(Double)、クラスの外部からそのようなオブジェクトを作成できます。したがって、値を格納するために、動的である可能性がある何らかの種類のListを使用することをお勧めします。

関連する問題