0

目标


我正在制作一个 Java 类,它将增强数组的可用性,例如addremovecontains方法。ArrayPP我认为最好的解决方案是创建一个具有类型参数的类(称为) T。这样,用户可以ArrayPP像使用相同类型的数组一样轻松地与对象交互。

问题


我很快发现这样add的方法需要创建一个单独的数组,并最终将目标数组t从 s 数组更改为Ts 数组Object。正如您可能猜到的那样,这完全破坏了可用性,当我尝试做类似的事情时

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;

因为该add方法必须将数组更改为Objects 的数组,因为 Java 编译器不会让您创建一个泛型数组(T[] t = new T[0];不好,但T[] t = (T[]) new Object[0];没关系)。我从逐行调试中知道,上面的代码保留了数组t,在这种情况下,作为 s 的数组,直到调用方法File的第 4 行。有没有人有一个解决方案可以使数组保持s 数组而不是 s 数组addtTObject

示例代码


下面是我班的一个非常淡化的版本。

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

In principle you can't easily create arrays of a generic type (or type variable).

If you have a class object, you can use reflection, or if you have an example array, the methods in the java.util.Arrays class to create a (longer/shorter) copy. But it is not elegant either way.

The ArrayList class internally simply uses an Object[] to store its elements, and converts only on get/set/add/toArray. What would your class do better than ArrayList?


Edit:

I would recommend either simply delegate to an ArraysList, or do the implementation like ArrayList does, using an Object[] internally, and converting on output where necessary.

If you really want to have an array of the right type internally, it is possible - but it gets ugly, as I said.

The add method is still the easiest case:

  /**
   * 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;
  }

When you want to add in the middle or remove, you'll have to combine this with your arraycopy.

于 2011-03-20T23:16:34.540 回答
1

Is there some reason the built-it List<T> class(es) can't do what you need? As in:

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 回答