获取组件类型的数组类

Tom*_*tle 42 java arrays

如果我有一个实例Class,有没有办法获得Class其数组类型的实例?我基本上要求的是等效于方法getArrayType的反转getComponentType()方法,例如:

array.getClass().getComponentType().getArrayType() == array.getClass()
Run Code Online (Sandbox Code Playgroud)

Boz*_*zho 53

我想到的一件事是:

java.lang.reflect.Array.newInstance(componentType, 0).getClass();
Run Code Online (Sandbox Code Playgroud)

但它创造了一个不必要的实例.

顺便说一句,这似乎工作:

Class clazz = Class.forName("[L" + componentType.getName() + ";");
Run Code Online (Sandbox Code Playgroud)

这是测试.它打印true:

Integer[] ar = new Integer[1];
Class componentType = ar.getClass().getComponentType();
Class clazz = Class.forName("[L" + componentType.getName() + ";");

System.out.println(clazz == ar.getClass());
Run Code Online (Sandbox Code Playgroud)

Class#getName()严格定义数组类名称格式的文档:

如果此类对象表示一个数组类,则名称的内部形式由元素类型的名称组成,前面有一个或多个'['字符,表示数组嵌套的深度.

这种Class.forName(..)方法不会直接用于原语 - 对于它们,你必须在name(int)和数组简写之间创建一个映射- (I)

  • `Class.forName()`方法也为字符串连接生成临时对象(例如new StringBuilder().append("[L").append(componentType.getName()).append(";").toString( )).所以我想第一种方法产生的分配更少,即使是不必要的分配. (3认同)
  • 您可能想要使用Class.forName("[L"+ componentType.getName()+";",false,componentType.getClassLoader()) (3认同)
  • 正如 @ɲeuroburɳ 所说,“Class.forName(…)”方法创建了更多临时对象,成本更高(类名越长,成本越高),此外,零大小的数组有更好的机会被删除优化器会这样做,但更糟糕的是,“Class.forName(…)”方法不仅不适用于原始类型,也不适用于数组类型(当尝试获取多维数组类型时)。而 `Array.newInstance(componentType, 0).getClass()` 就完成了这项工作。对于 Java 12+,您可以只使用“componentType.arrayType()”;猜猜它在幕后做了什么…… (3认同)

Fro*_*age 12

实际上由于ClassLoader原语和多维数组,答案有点复杂:

public static Class<?> getArrayClass(Class<?> componentType) throws ClassNotFoundException{
    ClassLoader classLoader = componentType.getClassLoader();
    String name;
    if(componentType.isArray()){
        // just add a leading "["
        name = "["+componentType.getName();
    }else if(componentType == boolean.class){
        name = "[Z";
    }else if(componentType == byte.class){
        name = "[B";
    }else if(componentType == char.class){
        name = "[C";
    }else if(componentType == double.class){
        name = "[D";
    }else if(componentType == float.class){
        name = "[F";
    }else if(componentType == int.class){
        name = "[I";
    }else if(componentType == long.class){
        name = "[J";
    }else if(componentType == short.class){
        name = "[S";
    }else{
        // must be an object non-array class
        name = "[L"+componentType.getName()+";";
    }
    return classLoader != null ? classLoader.loadClass(name) : Class.forName(name);
}
Run Code Online (Sandbox Code Playgroud)

  • 在最后一行中,您还可以将forName方法与class loader参数一起使用(这也适用于`null`,从而避免了区分大小写). (2认同)

Pet*_*rey 9

您可以执行以下操作

array.getClass() == 
    Array.newInstance(array.getClass().getComponentType(), 0).getClass()
Run Code Online (Sandbox Code Playgroud)

通常,您不需要知道类型,只需要创建数组.