java - 使用通用数组的 ArrayList 转换 ArrayList.toArray()

标签 java arrays generics casting arraylist

一个我几乎要放弃所有希望的难题。我想做一个 函数,但在获取 ArrayList.toArray() 返回我想要的类型时遇到问题。

这是演示我的问题的最小示例:

public static <T> T[] test(T one, T two) {
    java.util.List<T> list = new ArrayList<T>();
    list.add(one);
    list.add(two);
    return (T[]) list.toArray();
}

通常我可以使用 (T[]) list.toArray(new T[0]) 的形式,但是有两个额外的困难:

  1. 由于协方差规则,我无法对数组进行类型转换,(T[]) myObjectArray 给出了一个 ClassCastException
  2. 您不能创建泛型类型的新实例,这意味着我不能实例化 new T[]。我也不能对 ArrayList 的元素之一使用克隆或尝试获取它的类。

我一直在尝试使用以下调用获取一些信息:

public static void main(String[] args) {
   System.out.println(test("onestring", "twostrings"));
}

结果的形式为 [Ljava.lang.Object;@3e25a5,表明返回的类型转换无效。奇怪的是:

public static void main(String[] args) {
    System.out.println(test("onestring", "twostrings").getClass());
}

返回:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at patchLinker.Utilities.main(Utilities.java:286)

所以我最好的猜测是它认为它是一个 String 数组标签明智的,但在内部是一个 Object 数组,并且任何访问尝试都会导致这种不一致。

如果有人能找到解决此问题的任何方法(因为我拒绝了两种正常的解决方法),我将非常感激。

K·巴拉德 JDK1.6


编辑


感谢 Peter Lawrey 解决了最初的问题。现在的问题是如何使解决方案适用于我不那么简单的示例:

public static <T> T[] unTreeArray(T[][] input) {
    java.util.List<T> outList = new ArrayList<T>();
    java.util.List<T> tempList;
    T[] typeVar;
    for (T[] subArray : input) {
        tempList = java.util.Arrays.asList(subArray);
        outList.addAll(tempList);
    }
    if (input.length > 0) {
        typeVar = input[0];
    } else {
        return null;
    }
    return (T[]) outList.toArray((T[]) java.lang.reflect.Array.newInstance(typeVar.getClass(),outList.size()));
}

public static void main(String[] args) {
    String[][] lines = { { "111", "122", "133" }, { "211", "222", "233" } };
    unTreeArray(lines);
}

此时的结果是

Exception in thread "main" java.lang.ArrayStoreException
at java.lang.System.arraycopy(Native Method)
at java.util.ArrayList.toArray(Unknown Source)
at patchLinker.Utilities.unTreeArray(Utilities.java:159)
at patchLinker.Utilities.main(Utilities.java:301)

我仍在做一些测试,看看是否可以获得比这更有用的信息,但目前我不确定从哪里开始。我会添加我得到的任何更多信息。

K·巴拉德


编辑 2


现在有更多信息。我尝试手动构建数组并以元素方式传输项目,因此我将类型转换为 T,而不是 T[]。我发现了一个有趣的结果:

public static <T> T[] unTreeArray(T[][] input) {
    java.util.List<T> outList = new ArrayList<T>();
    java.util.List<T> tempList;
    T[] outArray;
    for (T[] subArray : input) {
        tempList = java.util.Arrays.asList(subArray);
        outList.addAll(tempList);
    }
    if (outList.size() == 0) {
        return null;
    } else {
        outArray = input[0];// use as a class sampler
        outArray =
                (T[]) java.lang.reflect.Array.newInstance(outArray.getClass(), outList.size());
        for (int i = 0; i < outList.size(); i++) {
            System.out.println(i + "  " + outArray.length + "   " + outList.size() + "   "  + outList.get(i));
            outArray[i] = (T) outList.get(i);
        }
        System.out.println(outArray.length);
        return outArray;
    }
}

我仍然得到以下输出:

0  6   6   111
Exception in thread "main" java.lang.ArrayStoreException: java.lang.String
at patchLinker.Utilities.unTreeArray(Utilities.java:291)
at patchLinker.Utilities.main(Utilities.java:307)

这是否意味着即使您设法间接创建一个 T[] 也不能写入?

最佳答案

toArray() 总是返回一个对象数组。

要返回特定类型的数组,需要使用 toArray(Object[])。

要为数组参数提供正确的类型,您需要使用特定的类,或者在本例中使用反射。

尝试

 return (T[]) list.toArray(Array.newInstance(one.getClass(), list.size()));

关于java - 使用通用数组的 ArrayList 转换 ArrayList.toArray(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4736419/

相关文章:

Java:有没有办法读取文件直到某个字符

java - ":"在 for 函数中代表什么

javascript - coinmarketcap api v2 jquery

c - 为什么这个 C 数组算法在第二次迭代时失败?

java 。泛型类中的方法总是返回 Object

java - 将支持 bean 实例作为参数传递给另一个支持 bean 方法

java - 如何从Camel路由的xsl apply-templates中传递参数

c++ - 需要将 ifstream 输入文件转换为我可以循环和解密的格式

c# - 实现接口(interface)

generics - F#独特的重载方法