在运行时获取数组类名称的安全方法是什么?

时间:2013-07-31 05:47:46

标签: java generics reflection

以下是一个示例代码,需要获取运行时未知的数组的类名:

//for calling methods declared similar to
//  void method(String... values);
//For primitive type we have other overloads and the following 
//is generic for classes 

@SuppressWarnings("unchecked")
private static <T> void invokeVaridic(Method m, Object host, T... values) 
    throws IllegalAccessException, IllegalArgumentException, 
    InvocationTargetException, ClassNotFoundException{

    assert(values.length>0); //We assume all users passes at least one value
    Class<? extends T[]> c = (Class<? extends T[]>) 
            Class.forName("[L" + values[0].getClass().getName() + ";");
    m.invoke(host, Arrays.copyOf(values, values.length,c));
}

由于类型擦除性质values的类型实际上是Object[],我无法将其传递给m.invoke,因为它需要String[]。但是,由于我强制用户传递至少一个值,我可以使用values[0]的类型来构造一个新数组。

我不知道T[].class是什么。

我想出了上面的代码,它依赖于字节代码中数组名称的解释,但它是否安全?获取T[].class的建议方法是什么?

2 个答案:

答案 0 :(得分:4)

values的类型为T[]

Class<? extends T[]> arrayType = (Class<? extends T[]>) values.getClass();
Class<? extends T> component = (Class<? extends T>) values.getClass().getComponent();

/编辑

完整示例:

public class GenericArray {
    public static void main(String[] args) {
        foo("", "");
    }

    @SafeVarargs
    public static <T> void foo(T... args) {
        Class<? extends T[]> array = (Class<? extends T[]>) args.getClass();
        Class<? extends T> component = (Class<? extends T>) array.getComponentType();
        System.out.println(array);
        System.out.println(component);
    }
}

使用JDK 1.7.0_25打印以下内容

class [Ljava.lang.String;
class java.lang.String

答案 1 :(得分:0)

您不一定能确定values中的值实际上是T类型,因为类型擦除的数组会受到堆污染,您应该准备好处理ClassCastException在你施展的那一刻。但是,您可以通过稍微复杂的Array.newInstance调用来获取特定对象的数组类型:

Class<?> arrayClass = Array.newInstance(values[0].getClass(), 1).getClass();