java - 数组连接和类型转换

标签 java generics

<分区>

我有一个实用程序:

public class ArrayUtils {
    public static <T> T[] concat(T[]... arrays) {
        if(arrays == null) {
            return null;
        }
        int size = 0;
        for(T[] array : arrays) {
            size += array.length;
        }

        T[] concatenatedArray = (T[]) new Object[size];

        int i = 0;
        for(T[] array : arrays) {
            for(T item : array) {
                concatenatedArray[i++] = item;
            }
        }

        return concatenatedArray;
    }
}

当我测试 concat 时,它崩溃了:

public class ArrayUtilsTest extends TestCase {

    public void testConcat() throws Exception {
        Integer[] first = new Integer[]{1,2,3};
        Integer[] second = new Integer[]{4,5,6};
        Integer[] concat = ArrayUtils.concat(first, second);
        assertEquals(6, concat.length);
    }
}

带有消息

java.lang.ClassCastException: java.lang.Object[] cannot be cast to java.lang.Integer[]

我想这与泛型有关。你能提供让它发挥作用的建议吗?另外,这个问题的背景会很好。

谢谢!

最佳答案

您的问题是您在 concat 方法中创建了一个 Object 数组。

代替

T[] concatenatedArray = (T[]) new Object[size];

使用

T[] concatenatedArray = (T[]) Array.newInstance(arrays[0].getClass()
        .getComponentType(), size);

更新:虽然上面的内容可能会为您完成工作,但 newacct 在评论中指出它使用起来更好/更安全

T[] concatenatedArray = (T[]) Array.newInstance(arrays.getClass()
        .getComponentType().getComponentType(), size);

这将允许您跳过尺寸检查并使用该方法,例如ArrayUtils.concat(new String[]{"foo"}, new Integer[]{42});(如果需要),否则会因 ArrayStoreException 而失败。

你可以忽略类型安全警告,因为你知道数组是T类型,但你应该确保你至少有一个数组。

你可以这样做,例如通过将您的方法签名修改为

public static <T> T[] concat(T[] array1, T[]... arrays);

作为一个简短的解释:这与泛型类型在 java 中的实现方式有关,参见。 https://docs.oracle.com/javase/tutorial/java/generics/genMethods.html .

实际上,您在 concat 中的第一次转换也应该失败(因为在这种情况下,您已经在尝试将 Object[] 转换为 Integer[] ),但由于类型删除,字节码将包含对 Object[] 的转换(您应该能够通过查看字节码或使用反编译器来验证这一点) .

另一方面,您的测试方法不是通用的,而是显式转换为 Integer[](即使在字节码中 ;)),因此它会失败。

最后但并非最不重要的一般经验法则:如果可能,请尝试使用现有的库,例如 Apache Commons而不是重新发明轮子。你会发现你的大部分问题在过去已经被其他人解决了 ;)

关于java - 数组连接和类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30504299/

相关文章:

java - 运行eclipse时电脑关闭

java - wsimport 不会为集合生成 setter

java - 前 1000 个质数之和

java - 如何打开OTG连接设置

c# - 按位运算符的通用约束

java - 使用事务和并行线程时错误的 Spring 缓存状态

java - Intellij 给出了奇怪的错误。 Java 泛型问题

ios - 如何在不同的类中使用公共(public)代码

Java Byte/字节数组空间效率比较

c# - 检查通用类型