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

Java 在运行时获取数组类名的安全方法是什么?,java,generics,reflection,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>

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

//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));
}
由于类型擦除的本质是值的类型实际上是Object[],因此我无法将其传递给m.invoke,因为它需要字符串[]。但是,由于我强制用户至少传递一个值,因此我可以使用值[0]的类型来构造新数组

我不知道t[]是什么。类

我提出了上面的代码,这取决于字节码中数组名称的解释,但它安全吗?获得T[]类的建议方法是什么

值的类型为T[]:

值的类型为T[]:


您不一定确定values中的值实际上是t类型的,因为类型擦除的数组会受到堆污染,您应该准备在您强制转换时处理ClassCastException。但是,您可以通过稍微复杂地调用array.newInstance来获取特定对象的数组类型:


您不一定确定values中的值实际上是t类型的,因为类型擦除的数组会受到堆污染,您应该准备在您强制转换时处理ClassCastException。但是,您可以通过稍微复杂地调用array.newInstance来获取特定对象的数组类型:


在运行时,即使T在编译时是字符串,值也将是Object[]类型;大多数情况下,使用正确的代码,值实际上是正确的类型。但是,可以通过一组裸对象;这个例子没有什么特别之处。@chrylis完全正确,在正常情况下,上面的代码可以工作。它不起作用的唯一原因是因为有人错误地处理了泛型类型,从而在代码中引入了一个bug。虽然它可以工作,但很抱歉,我不能从类型擦除的角度理解它。我认为在运行时VAL将是Object[]。让我困惑的是类型转换。你能解释一下Class arrayType=Class values.getClass;这种石膏不一定安全。运行时的值类可以是U[],其中U是T的子类型。在运行时,最多可以说是ClassAt,值的类型将是Object[],即使T在编译时是String;大多数情况下,使用正确的代码,值实际上是正确的类型。但是,可以通过一组裸对象;这个例子没有什么特别之处。@chrylis完全正确,在正常情况下,上面的代码可以工作。它不起作用的唯一原因是因为有人错误地处理了泛型类型,从而在代码中引入了一个bug。虽然它可以工作,但很抱歉,我不能从类型擦除的角度理解它。我认为在运行时VAL将是Object[]。让我困惑的是类型转换。你能解释一下Class arrayType=Class values.getClass;这种石膏不一定安全。值的运行时类可以是U[],其中U是T的子类型。您最多只能说任何对象上的ClassgetClass将返回其运行时类,而getClass.getName将以字符串形式返回类名。执行getClass.getName后跟classForName只是执行getClass.And执行Class.forName[L+值[0]的低效方法.getClass.getName+;是执行值的低效方法。任何对象上的getClass.getClass将返回其运行时类,而getClass.getName将以字符串形式返回类名。执行getClass.getName后跟classForName只是执行getClass.and执行Class.forName[L+值[0]的低效方法.getClass.getName+;是执行值的低效方法。getClass。@热舔值[0].getClass获取位于位置0的元素的类,而不是数组类本身。好的,你得到了我。不清楚OP是否试图缩小数组的类。但是他当然必须检查数组的所有元素以确保。第一个元素可以是字符串,第二个元素可以是土豆。如果他想要数组的类数组值本身,然后是values.getClass。你不能再精确了。@HotLicks…你读过问题的解释或我回答中的警告了吗?对不起,我被堆污染挂断了。这到底是什么意思?@HotLicks values[0].getClass获取位于位置0的元素的类,而不是数组类本身。好的,你得到了我。不清楚OP是否试图缩小数组的类。但是他当然必须检查数组的所有元素以确保。第一个元素可以是字符串,第二个元素可以是土豆。如果他想要数组的类数组值本身然后是值。getClass就是它。你无法得到更精确的结果。@HotLicks…你读过问题的解释或我回答中的警告了吗?对不起,我被堆污染挂断了。这到底是什么意思?
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);
    }
}
class [Ljava.lang.String;
class java.lang.String
Class<?> arrayClass = Array.newInstance(values[0].getClass(), 1).getClass();