在Java中可以使用数组varargs吗?

时间:2016-04-30 14:56:49

标签: java variadic-functions

我试图实现一种方法来合并任意数量的数组。

@SuppressWarnings("unchecked")
public static <T> T[] merge(T[]... arrs) {
    int length = 0;
    for (T[] arr : arrs) {
        length += arr.length;
    }

    T[] merged = (T[]) new Object[length];
    int destPos = 0;
    for (T[] arr : arrs) {
        System.arraycopy(arr, 0, merged, destPos, arr.length);
        destPos += arr.length;
    }
    return merged;
}
它编译了,看起来没问题。然后我像这样测试了这个方法:

    String[] a = {"a", "b", "c"};
    String[] b = {"e", "f"};
    String[] c = {"g", "h", "i"};

    String[] m = merge(a,b,c);

虽然此代码已成功编译,但它会引发异常:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
    at ntalbs.test.ArrayMerge.main(ArrayMerge.java:25)

代码看似合理并且编译成功,但不起作用并在运行时抛出异常。你能解释为什么这段代码不起作用吗?我错过了什么?

5 个答案:

答案 0 :(得分:5)

问题与varargs没有任何关系。

正如错误消息所示:您的方法会创建并返回Object[],并且您将其转换为String[]。但Object[]不是String[]。因此例外。

查看Collection的源代码(及其T[] toArray()方法),了解它基本上可以执行的操作:创建类型为T[]的数组。< / p>

答案 1 :(得分:2)

您可以通过T&#39课程创建一个数组。由于您传入了对象,因此可以从其中一个获取类型。像这样:

home/usr/.../lib/python2.7/dist-packages/cv2.so

然后填充数组。

答案 2 :(得分:2)

你的问题不是因为varargs。

因为这条线,

T[] merged = (T[]) new Object[length];

无法将Object数组强制转换为String数组。

使用,

T[] merged = (T[])java.lang.reflect.Array.newInstance(
                            arrs[0].getClass().getComponentType(), length);

注意:

正如@JB所指出的,只有在尝试合并相同的数组类型时才会有效。如果要合并不同的数组类型,则必须找到所有数组通用的超类型,并使用它代替arrs[0].getClass()

答案 3 :(得分:0)

您无法将Object []强制转换为String []。您需要创建正确运行时类型的实例。 为此,您可以使用java.lang.reflect.Array #newInstance方法。要获得正确的类型,可以按如下方式向merge方法添加Class参数:

    String[] a = { "a", "b", "c" };
    String[] b = { "e", "f" };
    String[] c = { "g", "h", "i" };

    String[] m = merge(String.class, a, b, c);

这可以在没有运行时异常的情况下执行:

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

RewriteRule ^profile/([^/]+)/?$ profile.php?u=$1 [NC,QSA,L]

RewriteRule ^welcome/([^/]+)/?$ index.php?a=welcome&filter=$1 [NC,QSA,L]

RewriteRule ^page/([^/]+)/?$ index.php?a=page&filter=$1 [NC,QSA,L]

RewriteRule ^(([^/]+)+)(/([^/]{0,32})(/.+)?)?$ index.php?a=$1&q=$3 [L,QSA]

答案 4 :(得分:0)

varargs 适用于所有Java类型。上述异常由行T[] merged = (T[]) new Object[length];生成,与 varargs 无关。

数组不是通用的。我建议改为使用Collections框架。

如果您无法更改代码结构,请尝试与此类似的内容:

@SuppressWarnings("unchecked")
public static <T> T[] merge(T[]... arrays) {
    int fullSize = 0;
    for (T[] array: arrays) {
        fullSize += array.length;
    }
    List<T> concatenatedList = new ArrayList<T>(fullSize);
    for (T[] array: arrays) {
        concatenatedList.addAll(Arrays.asList(array));
    }
    Class<T> targetType = (Class<T>)arrays
        .getClass().getComponentType().getComponentType()
    ;
    return concatenatedList.toArray(
        (T[])Array.newInstance(targetType, concatenatedList.size())
    );
}