0

ゴール


add、、メソッドremoveなどの配列の使いやすさを向上させるJavaクラスを作成していますcontains。最善の解決策はArrayPP、型パラメーターを持つクラス(と呼ばれる)を作成することだと思いましたT。このようにして、ユーザーArrayPPは同じタイプの配列を使用するのと同じくらい簡単にオブジェクトを操作できます。

問題


私はすぐaddに、別の配列を作成する必要があり、ターゲット配列をsのt配列からsの配列に変更するような方法を見つけました。ご想像のとおり、これはユーザビリティを完全に破壊します。TObject

File[] f = new File[0];
ArrayPP<File> appF = new ArrayPP(f);
appF.add(saveFile);
f = appF.toArray();

プログラムはスローします

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.io.File;

これは、Javaコンパイラではジェネリック配列を作成できないため、addメソッドは配列をsの配列に変更する必要があるためです(悪いですが、問題ありません)。行ごとのデバッグから、上記のコードが配列を保持していることがわかります。この場合は、メソッドの4行目が呼び出されるまでsの配列として保持されます。配列をsの配列ではなくsの配列に保つソリューションを誰かが持っていますか?ObjectT[] t = new T[0];T[] t = (T[]) new Object[0];tFileaddtTObject

サンプルコード


以下は私のクラスの非常に骨抜きにされたバージョンです。

public class ArrayPP<T>
{
  T[] t;

  /**
   * Creates a new Array++ to manage the given array.
   * <h3>Analogy:</h3>
   * <tt>ArrayPP&lt;String&gt; s = new ArrayPP(args);</tt><br/>
   * is analogous to<br/>
   * <tt>String s[] = args;</tt>
   * @param array The array to be managed
   */
  public ArrayPP(T[] array)
  {
    t = array;
  }

  /**
   * Appends a value to the end of the array
   * @param val the value to be appended
   * @return the resulting array.
   */
  public ArrayPP add(T val)
  {
    T[] temp = (T[]) new Object[t.length + 1];
    System.arraycopy(t, 0, temp, 0, t.length);
    temp[temp.length - 1] = val;
    t = (T[])temp;
    return this;
  }

  /**
   * Returns the array at the core of this wrapper
   * @return the array at the core of this wrapper
   */
  public T[] toArray()
  {
    return t;
  }
}

考えられる解決策は?


ジェネリック配列に関する他の質問を見た後、私は解決策があると思います:

それ以外の

  /**
   * Appends a value to the end of the array
   * @param val the value to be appended
   * @return the resulting array.
   */
  public ArrayPP add(T val)
  {
    T[] temp = (T[]) new Object[t.length + 1];
    System.arraycopy(t, 0, temp, 0, t.length);
    temp[temp.length - 1] = val;
    t = (T[])temp;
    return this;
  }

これは機能しますか?

  /**
   * Appends a value to the end of the array
   * @param val the value to be appended
   * @return the resulting array.
   */
  public ArrayPP<T> add(T val)
  {
    t = java.util.Arrays.copyOf(t, t.length + 1);
    t[t.length - 1] = val;
    return this;
  }
4

3 に答える 3

2

原則として、ジェネリック型(または型変数)の配列を簡単に作成することはできません。

クラスオブジェクトがある場合は、リフレクションを使用できます。サンプル配列がある場合は、java.util.Arraysクラス内のメソッドを使用して(長い/短い)コピーを作成できます。しかし、どちらにしてもエレガントではありません。

ArrayListクラスは、内部的に単にObject[]要素を格納するためにを使用し、get / set / add/toArrayでのみ変換します。あなたのクラスはArrayListよりも優れていますか?


編集:

単にArraysListに委任するか、ArrayListのように実装を行い、Object[]内部で使用し、必要に応じて出力を変換することをお勧めします。

本当に適切な型の配列を内部に持たせたいのであれば、それは可能ですが、私が言ったように、それは醜くなります。

このadd方法は依然として最も簡単なケースです。

  /**
   * Appends a value to the end of the array
   * @param val the value to be appended
   * @return the resulting array.
   */
  public ArrayPP add(T val)
  {
     T[] temp = Arrays.copyOf(t, t.length+1);
     temp[t.length] = val;
     t = temp;
     return this;
  }

途中で追加または削除する場合は、これをアレイコピーと組み合わせる必要があります。

于 2011-03-20T23:16:34.540 に答える
1

List<T>ビルドされたクラスが必要なことを実行できない理由はありますか?のように:

String[] theArray = {"a", "b", "c"};
List<String> theList = Arrays.asList(theArray);
于 2011-03-20T23:15:53.880 に答える
0
public ArrayPP(T[] array)
    componentClass = array.getClass().getComponentClass();

T[] newArray(int length)
    return Array.newInstance(componentClass, length)
于 2011-03-20T23:11:26.743 に答える