Java 使用泛型数组的ArrayList强制转换ArrayList.toArray()

Java 使用泛型数组的ArrayList强制转换ArrayList.toArray(),java,arrays,generics,casting,arraylist,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[])

这是一个我几乎要放弃所有希望的难题。我在试着做一个决定 函数,但在获取
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();
}
结果是
[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)
所以我最好的猜测是,它认为它是一个字符串数组标签,但在内部是一个对象数组,任何访问的尝试都会带来这种不一致性

如果有人能找到解决这个问题的方法(因为我没有两个正常的解决办法),我会非常感激

巴拉德 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);
}
我仍在做一些测试,看看是否能得到比这更有用的信息,但目前我不确定从哪里开始。我会在得到更多信息时添加这些信息

巴拉德


编辑2


现在有更多信息。我尝试手动构建数组并以elementwise方式传输项,因此我将以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;
    }
}
这是否意味着即使您设法间接创建了一个
t[]
,也无法对其进行写入?

toArray()始终返回一个对象数组

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

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

试一试


不能创建泛型类型参数的数组。原因很简单,java通常在运行时删除泛型类型信息,因此运行时不知道t是什么(当t是泛型类型参数时)

因此,解决方案是在运行时实际获取类型信息。通常通过传递
类类型
参数来实现,但在这种情况下,您可以避免:

@彼得的答案看起来不错,我会用它:)


第二个代码示例上的问题是由
T[]typeVar
引起的:输入是一个两维数组,因此
Input[0]
将返回一个一维数组(字符串[],而不是预期的字符串)

如果要将
列表
转换为
T[]
,则需要一个
T typeVar

要解决此问题,请执行以下操作:

public static <T> T[] unTreeArray(T[][] input) {
    java.util.List<T> outList = new ArrayList<T>();
    java.util.List<T> tempList;

    if (input.length == 0) {
        return null;
    }


    T typeVar=null;
    for (T[] subArray : input) {
        if(typeVar==null && subArray.length>0) {
            typeVar=subArray[0];
        }
        tempList = java.util.Arrays.asList(subArray);
        outList.addAll(tempList);
    }

    return outList.toArray((T[]) Array.newInstance(typeVar.getClass(),0));
}

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

    System.out.println(result);

    System.out.println(result.getClass());

        //added for completion:
    System.out.println( Arrays.toString(result));

}
publicstatict[]unTreeArray(T[]input){
java.util.List outList=新的ArrayList();
java.util.List模板列表;
if(input.length==0){
返回null;
}
T typeVar=null;
对于(T[]子阵列:输入){
if(typeVar==null&&subArray.length>0){
typeVar=子数组[0];
}
templast=java.util.Arrays.asList(子数组);
亚德尔(圣殿骑士);
}
返回outList.toArray((T[])Array.newInstance(typeVar.getClass(),0));
}
公共静态void main(字符串[]args){
字符串[][]行={{“111”、“122”、“133”}、{“211”、“222”、“233”};
字符串[]结果=未搜索数组(行);
系统输出打印项次(结果);
System.out.println(result.getClass());
//添加以完成:
System.out.println(Arrays.toString(result));
}
结果输出:

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)
[Ljava.lang.String;@5a405a4类
[Ljava.lang.String;
[11112213321222233]


感谢您的快速响应。我尝试了这个方法,但它给出了一个相当模糊的错误:类型列表中的toArray(T[])方法不适用于参数(对象)。我做了一些手动检查,我可以在实例上调用getClass(),所以我怀疑是因为newInstance()返回一个Object您应该在Array.newInstance方法结果上添加强制转换。例如:list.toArray((T[])Array.newInstance(one.getClass(),0))@K.Barad它需要另一个强制转换。如果两个对象的类型不同,或者如果调用方修改了返回的数组,则也会出现问题。谢谢,我忘记了转换Object=>T[]是有效的,只有对象[]=>T[]无效。现在来测试它在my中是否有效(稍微不那么繁琐)真正的方法。谢谢你的帮助,希望这能解决。不走运。有可能我犯了一些愚蠢的错误,我看到这段代码太久了,没有间断。我建议坚持使用集合,留下老式的引用数组。我很乐意,但有时你在这件事上别无选择。向后兼容ty总是暗示某些东西是落后的。是的,我花了几个多小时搜索阅读了所有的文章(承认相当不错)为什么泛型不能让我得到一个简单的解决方案。好吧,我肯定有一个疯狂的时刻。当然,你传递给它的是元素而不是数组类型,或者什么是重点?谢谢你,似乎所有的东西都终于起作用了。发生了很多。有时我们从太接近我们自己的代码的地方寻找隐藏的错误:)问题到@TomasNarros Wh如果输入数组为空,那么typeVar将保留为NULL,因此您得到了一个NullPointerException。在这种情况下如何返回空列表?如果输入可以为NULL,您应该首先检查,更改
if(input.length==0)
if(input!=NULL&&input.length==0)
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)
 return (T[]) list.toArray(Array.newInstance(one.getClass(), list.size()));
return (T[]) list.toArray(Array.newInstance(one.getClass(), list.size()));
public static <T> T[] unTreeArray(T[][] input) {
    java.util.List<T> outList = new ArrayList<T>();
    java.util.List<T> tempList;

    if (input.length == 0) {
        return null;
    }


    T typeVar=null;
    for (T[] subArray : input) {
        if(typeVar==null && subArray.length>0) {
            typeVar=subArray[0];
        }
        tempList = java.util.Arrays.asList(subArray);
        outList.addAll(tempList);
    }

    return outList.toArray((T[]) Array.newInstance(typeVar.getClass(),0));
}

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

    System.out.println(result);

    System.out.println(result.getClass());

        //added for completion:
    System.out.println( Arrays.toString(result));

}