有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用数组复制不同类型的数组时出现java问题。副本

我试图创建一个方法,该方法几乎可以将任何内容作为参数,并返回带有分隔符的值的串联字符串表示形式

public static String getConcatenated(char delim, Object ...names) {
String[] stringArray = Arrays.copyOf(names, names.length, String[].class); //Exception here
return getConcatenated(delim, stringArray);
}

以及实际的方法

public static String getConcatenated(char delim, String ... names) {
if(names == null || names.length == 0)
    return "";

StringBuilder sb = new StringBuilder();

for(int i = 0; i < names.length; i++) {
    String n = names[i];
    if(n != null) {
        sb.append(n.trim());
        sb.append(delim);
    }
}

//Remove the last delim
return sb.substring(0, sb.length()-1).toString();
}

我有以下JUnit测试:

final String two = RedpillLinproUtils.getConcatenated(' ', "Shervin", "Asgari");
Assert.assertEquals("Result", "Shervin Asgari", two); //OK

final String three = RedpillLinproUtils.getConcatenated(';', "Shervin", "Asgari");
Assert.assertEquals("Result", "Shervin;Asgari", three); //OK

final String four = RedpillLinproUtils.getConcatenated(';', "Shervin", null, "Asgari", null);
Assert.assertEquals("Result", "Shervin;Asgari", four); //OK

final String five = RedpillLinproUtils.getConcatenated('/', 1, 2, null, 3, 4);
Assert.assertEquals("Result", "1/2/3/4", five); //FAIL

但是,最后一部分的测试失败,例外情况如下:

java.lang.ArrayStoreException at java.lang.System.arraycopy(Native Method) at java.util.Arrays.copyOf(Arrays.java:2763)

有人能发现错误吗


共 (3) 个答案

  1. # 1 楼答案

    由于不能在String[]数组中存储,例如Integers,因此无法将对象数组复制到字符串数组中。你必须以某种方式通过每个对象上的.toString()

    例如,该解决方案可以:

    public static String concat(char delim, Object... objs) {
        if (objs == null || objs.length == 0) return "";
        StringBuilder sb = new StringBuilder();
        for (Object o : objs)
            sb.append(delim).append(o);
        return sb.substring(1);
    }
    

    作为varargs的旁注;我怀疑你是否需要检查一下。编译器将把从concat(",", "a", "b", "c")的调用转换为concat(",", new Object[] {"a", "b", "c"),因此我看不出objs怎么可能等于null>

  2. # 2 楼答案

    原因

    你不能把Integer放在String[]里。这就是为什么你会得到ArrayStoreExceptionArrays.copyOf不进行转换

    the API

    T[] copyOf(U[] original, int newLength, Class< ? extends T[]> newType)

    Throws: ArrayStoreException - if an element copied from original is not of a runtime type that can be stored in an array of class newType

    {a2}有一个例子:

    Thrown to indicate that an attempt has been made to store the wrong type of object into an array of objects. For example, the following code generates an ArrayStoreException:

        Object x[] = new String[3];
        x[0] = new Integer(0);
    

    另见


    修复

    也就是说,你实际上不需要一个String...Arrays.copyOf到一个String[]。你的getConcatenated只需要Object...就行了

    public static String getConcatenated(char delim, Object... objs) {
        if(objs == null || objs.length == 0)
            return "";
    
        StringBuilder sb = new StringBuilder();
        for (Object o : objs) {
            if(o != null) {
                if (sb.length() > 0) sb.append(delim);
                sb.append(o.toString().trim());
            }
        }
        return sb.toString();
    }
    

    现在,您可以执行以下操作:

        System.out.println(getConcatenated(';', "Shervin", null, "Asgari", null));
        // prints "Shervin;Asgari"
    
        System.out.println(getConcatenated('/', 1, 2, null, 3, 4));
        // prints "1/2/3/4"
    
        System.out.println(getConcatenated(':', "  ", null, "boo", "boo"));
        // prints "boo:boo"
    

    请注意,这遵循了原始代码中的预期规范,即trim()和跳过null

  3. # 3 楼答案

    只能将String复制到String[]

    System#arraycopyArrays#copyOf不进行任何类型转换,您必须自己一个接一个地将对象转换为字符串,例如通过调用String#valueOf(空安全版本的Object#toString

    为什么不将方法更改为接受Object...而不是String...并对它们中的每一个调用String.valueOf(obj)