【问题标题】:Java generics and Array'sJava 泛型和数组
【发布时间】:2011-05-26 12:53:57
【问题描述】:

当我对我的单元测试运行它时,下面的 sn-p 是有意义的。我在标有“>>>>”的行上得到一个 ClassCastException(对象不能转换为字符串)。这种类型的操作可以在泛型中完成吗?

public class ArrayUtils<E> {

    public static <E> E[] appendToArray(E[] array, E item) {
        E[] result = (E[])new Object[array.length+1];
        for(int i=0; i < array.length; i++ ) {
            result[i] = array[i];
        }
        result[result.length-1] = item;
        return result;
    }

}

   @Test
   public void testAppendToArray() {
       String[] array = new String[1];
       array[0] = "a";

       assertSame("Array is not correct length.", 1, array.length );
>>>>   String[] appendToArray = ArrayUtils.<String>appendToArray(array, "b");
       assertSame("Array is not correct length.", 2, appendToArray.length );
    }

【问题讨论】:

  • 有什么原因这个`E[] result = (E[])new Object[array.length+1];`不能是E[] result = new E[array.length+1];(我没做过多少Java泛型,也许这是被禁止的,但它似乎可以解决它?)
  • @Noon Silk,禁止使用,因为E甚至不是类,而是TypeParameter。
  • 老实说,留下参考数组。

标签: java generics


【解决方案1】:

您将Object 转换为String,IOW,一个超类到继承的类。 它总是被禁止的。正如 AlexR 建议的那样,使用Arrays.newInstance()。但在这种情况下,您必须在此处传递对象的类:

ArrayUtils.<String>append(array, "b", String.class);

我建议你不要尝试实现这种动态扩展数组的标准行为:它已经在ArrayList 类中实现了。您可以查看源代码以了解它是如何处理泛型的。

【讨论】:

    【解决方案2】:

    你不应该使用 new Object[] 创建你的数组。你应该改用Array.newInstance(Class clazz, int length)

    【讨论】:

      【解决方案3】:

      我不知道这段代码是做什么用的,但它给垃圾收集器带来了负担,因为要添加一个元素,就需要分配一个新数组。为此,您应该使用List 的任何实现,例如ArrayList

      【讨论】:

        【解决方案4】:

        不幸的是,Java中没有办法动态创建泛型类型的数组,因为在运行时没有携带泛型类型(E)的相关信息,所以无法知道要创建什么类型的数组创建。

        为了解决这个问题,我建议使用与 one used in collections library 类似的解决方案

        T[] java.util.List.toArray(T[] array)
        

        方法。也就是说,不要在 appendToArray 函数中创建新数组,而是从外部传递它。那就是:

        public static <E> E[] appendToArray(E[] array, E item, E[] newArray) {
          ... your code ...
        }
        
        @Test
        public void test(){
          appendToArray(array, "b", new String[array.length+1]);
        }
        

        我知道这看起来不像其他解决方案那么好,但它是类型安全的,并且具有更好的性能,因为它不诉诸反射。因此,建议您使用

        T[] java.util.List.toArray(T[] array)
        

        它的反射等效方法

        T[] java.util.List.toArray()
        

        【讨论】:

          【解决方案5】:

          正如其他人所说,您应该使用Array.newInstance() 创建正确类型的数组的实例。更有帮助的是,你可以从原始数组的类中得到你需要的组件类型。

          另外,我使用System.arraycopy()简化了复制。

          public static <E> E[] appendToArray(E[] array, E item) {
              E[] result = (E[])java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), array.length+1);
              System.arraycopy(array, 0, result, 0, array.length);
              result[result.length-1] = item;
              return result;
          }
          

          在 Java 1.6+ 中,您可以这样做:

          public static <E> E[] appendToArray(E[] array, E item) {
              E[] result = java.util.Arrays.copyOf(array, array.length+1);
              result[result.length-1] = item;
              return result;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-25
            • 2013-11-30
            • 2010-10-02
            • 1970-01-01
            • 2013-06-27
            • 2019-01-06
            • 2012-01-06
            相关资源
            最近更新 更多