Java 获取组件类型的数组类

Java 获取组件类型的数组类,java,arrays,Java,Arrays,如果我有一个类的实例,是否有方法为其数组类型获取类实例?我本质上要求的是一个方法getArrayType的等价物,它与getComponentType()方法相反,因此: array.getClass().getComponentType().getArrayType() == array.getClass() 您可以执行以下操作 array.getClass() == Array.newInstance(array.getClass().getComponentType(), 0)

如果我有一个
类的实例
,是否有方法为其数组类型获取
实例?我本质上要求的是一个方法
getArrayType
的等价物,它与
getComponentType()
方法相反,因此:

array.getClass().getComponentType().getArrayType() == array.getClass()

您可以执行以下操作

array.getClass() == 
    Array.newInstance(array.getClass().getComponentType(), 0).getClass()

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

想到的一件事是:

java.lang.reflect.Array.newInstance(componentType, 0).getClass();
但它创建了一个不必要的实例

顺便说一句,这似乎是可行的:

Class clazz = Class.forName("[L" + componentType.getName() + ";");
这是测试。它打印<代码>真:

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

System.out.println(clazz == ar.getClass());
严格定义数组类名称的格式:

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


但是,
Class.forName(…)
方法不能直接用于原语-对于它们,您必须在名称(
int
)和数组速记(
I
)之间创建映射-

另一种可能的重构是使用泛型超类并将两个类对象传递给构造函数

protected AbstractMetaProperty(Class<T> valueClass, Class<T[]> valueArrayClass) {
  this.valueClass = valueClass;
  this.valueArrayClass = valueArrayClass;
}

然后在抽象类中可以使用
valueClass.cast(x)
valueArrayClass.isInstance(x)
等。

实际上,由于
类加载器
、原语和多维数组,答案稍微复杂一些:

公共静态类getArrayClass(类componentType)引发ClassNotFoundException{
ClassLoader ClassLoader=componentType.getClassLoader();
字符串名;
if(componentType.isArray()){
//只需添加一个前导“[”
name=“[”+componentType.getName();
}else if(componentType==boolean.class){
name=“[Z”;
}else if(componentType==字节.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”;
}否则{
//必须是对象非数组类
name=“[L”+componentType.getName()+”;”;
}
返回classLoader!=null?classLoader.loadClass(名称):Class.forName(名称);
}

第一个版本(使用
Array.newInstance(…).getClass()
)适用于原语。这非常有用,谢谢。出于我的目的,我不需要处理原语,所以两种方法都可以使用。
Class.forName()
方法还为字符串连接生成临时对象(例如,new StringBuilder().append(“[L”).append(componentType.getName()).append(“;”).toString())。因此我认为第一种方法产生的分配更少,即使是不必要的分配。您可能希望使用Class.forName(“[L”+componentType.getName()+”),false,componentType.getClassLoader()),正如@ɲeuroburɳ所说,
Class.forName(…)
方法会创建更多的临时对象,成本更高(类名越长,成本越高),而且,零大小的数组被优化器删除的可能性更大,但更糟糕的是,
类.forName(…)
方法不仅不适用于基元类型,也不适用于数组类型(当尝试获取多维数组类型时)。而
array.newInstance(componentType,0)。getClass()只做这项工作。
使用Java 12+,您可以只使用
componentType.arrayType()
;猜猜它在引擎盖下做了什么……在最后一行中,您还可以使用带有类加载器参数的forName方法(它也适用于
null
,从而避免区分大小写)。最后一行不适用于我,但forName与类加载器一样适用于参数。
public IntegerClass() {
  super(Integer.class, Integer[].class);
}