如何在Java中获取给定类的数组类?

Posted

技术标签:

【中文标题】如何在Java中获取给定类的数组类?【英文标题】:How to get the Array Class for a given Class in Java? 【发布时间】:2010-12-13 08:37:35 【问题描述】:

我有一个持有某种类型的Class 变量,我需要获取一个持有相应数组类的变量。我能想到的最好的是:

Class arrayOfFooClass = java.lang.reflect.Array.newInstance(fooClass, 0).getClass();

有没有办法在不创建新实例的情况下做到这一点?

【问题讨论】:

【参考方案1】:

如果您不想创建实例,可以手动创建数组的规范名称并通过名称获取类:

// Replace `String` by your object type.
Class stringArrayClass = Class.forName(
    "[L" + String.class.getCanonicalName() + ";"
);

但是Jakob Jenkov argues in his blog 你的解决方案更好,因为它不需要摆弄字符串。

Class stringArrayClass = Array.newInstance(String.class, 0).getClass();

【讨论】:

他从上面开始,到我所拥有的结束。所以我猜newInstance 是最干净的方法。 它实际上是双向的,但你说你不想创建一个新实例。 是的。我实际上是在寻找更清洁的解决方案。不是我不想要新实例,而是我宁愿没有一个:-)【参考方案2】:

从 Java 12 开始,就有了arrayType() method on java.lang.Class。有了这个:

Class<?> arrayOfFooClass = fooClass.arrayType();

【讨论】:

【参考方案3】:

您可以使用类名来获取它。 只要确保你使用它的 ClassLoader 获取类

    Class klass = yourClass;
    boolean init = wantToDoStaticOperations;
    Class.forName("[L" + klass.getName() + ";", init, klass.getClassLoader());

【讨论】:

【参考方案4】:
Class stringArrayOfClass = String[].class;

【讨论】:

事先不知道类型;它在一个类变量中。所以你的方法行不通。【参考方案5】:

所以,我喜欢摆弄字符串。所以,这里有一个更通用的解决方案,它采用这种方法,并且仍然适用于任意类类型。它肯定比你的答案更繁琐,但无论如何,让它通用比公认的答案更复杂,所以这里是使它工作的完整代码集:

    /**
     * Returns the name of the class, as the JVM would output it. For instance, for an int, "I" is returned, for an
     * array of Objects, "[Ljava/lang/Object;" is returned. If the input is null, null is returned.
     *
     * @param clazz
     * @return
     */
    public static String getJVMName(Class clazz) 
        if(clazz == null) 
            return null;
        
        //For arrays, .getName() is fine.
        if(clazz.isArray()) 
            return clazz.getName().replace('.', '/');
        
        if(clazz == boolean.class) 
            return "Z";
         else if(clazz == byte.class) 
            return "B";
         else if(clazz == short.class) 
            return "S";
         else if(clazz == int.class) 
            return "I";
         else if(clazz == long.class) 
            return "J";
         else if(clazz == float.class) 
            return "F";
         else if(clazz == double.class) 
            return "D";
         else if(clazz == char.class) 
            return "C";
         else 
            return "L" + clazz.getName().replace('.', '/') + ";";
        
    

    /**
     * Generically and dynamically returns the array class type for the given class type. The dynamic equivalent of
     * sending @code String.class and getting @code String[].class. Works with array types as well.
     * @param clazz The class to convert to an array type.
     * @return The array type of the input class.
     */
    public static Class<?> getArrayClassFromType(Class<?> clazz) 
        Objects.requireNonNull(clazz);
        try 
            return Class.forName("[" + getJVMName(clazz).replace('/', '.'));
         catch(ClassNotFoundException ex) 
            // This cannot naturally happen, as we are simply creating an array type for a real type that has
            // clearly already been loaded.
            throw new NoClassDefFoundError(ex.getMessage());
        
    

请注意,这是我编写的现有库中的代码,这就是我使用 getJVMName 方法的原因。可能可以对其进行修改以保留点而不是 /,但鉴于它是这样工作的,我在这两种方法之间来回转换。无论如何,这适用于任何类,包括嵌套数组类型。

【讨论】:

以上是关于如何在Java中获取给定类的数组类?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中获取调用类的名称?

如何在 Python 中获取类的文件路径?

如何在Java中获取当前类名,包括包名?

给定一个任意长度的java数组,如何算出数组内的数能组合出来的最大整数?

03 Java 虚拟机是如何加载 Java 类的

JVM-Java 虚拟机是如何加载 Java 类的