【发布时间】:2011-06-21 12:42:41
【问题描述】:
如果我有Class 的实例,有没有办法为其数组类型获取Class 实例?我本质上要求的是方法 getArrayType 的等价物,它是 getComponentType() 方法的逆方法,这样:
array.getClass().getComponentType().getArrayType() == array.getClass()
【问题讨论】:
如果我有Class 的实例,有没有办法为其数组类型获取Class 实例?我本质上要求的是方法 getArrayType 的等价物,它是 getComponentType() 方法的逆方法,这样:
array.getClass().getComponentType().getArrayType() == array.getClass()
【问题讨论】:
想到的一件事是:
java.lang.reflect.Array.newInstance(componentType, 0).getClass();
但它会创建一个不必要的实例。
顺便说一句,这似乎有效:
Class clazz = Class.forName("[L" + componentType.getName() + ";");
这里是测试。它打印true:
Integer[] ar = new Integer[1];
Class componentType = ar.getClass().getComponentType();
Class clazz = Class.forName("[L" + componentType.getName() + ";");
System.out.println(clazz == ar.getClass());
The documentation of Class#getName()严格定义了数组类名的格式:
如果该类对象表示一类数组,则名称的内部形式由元素类型的名称组成,前面有一个或多个“[”字符,表示数组嵌套的深度。
Class.forName(..) 方法不能直接用于基元 - 对于它们,您必须在名称 (int) 和数组简写 - (I) 之间创建一个映射
【讨论】:
Array.newInstance(...).getClass())确实适用于原语。
Class.forName() 方法还为字符串连接生成临时对象(例如 new StringBuilder().append("[L").append(componentType.getName()).append(";" ).toString())。所以我想第一种方法会产生更少的分配,即使是不必要的。
Class.forName(…) 方法会创建更多的临时对象,成本更高(类名越长,成本越高),此外,零大小的数组有更好的机会被优化器删除,但更糟糕的是,Class.forName(…) 方法不仅不适用于原始类型,也不适用于数组类型(当尝试获取多维数组类型时)。而Array.newInstance(componentType, 0).getClass() 只是完成这项工作。对于 Java 12+,您可以只使用 componentType.arrayType();猜猜它在引擎盖下做了什么……
其实由于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);
}
【讨论】:
null,从而避免区分大小写)。
您可以执行以下操作
array.getClass() ==
Array.newInstance(array.getClass().getComponentType(), 0).getClass()
通常不需要知道类型,只需要创建数组即可。
【讨论】:
另一种可能的重构是使用泛型超类并将两个类对象传递给构造函数。
protected AbstractMetaProperty(Class<T> valueClass, Class<T[]> valueArrayClass) {
this.valueClass = valueClass;
this.valueArrayClass = valueArrayClass;
}
然后在子类中:
public IntegerClass() {
super(Integer.class, Integer[].class);
}
然后在抽象类中可以使用valueClass.cast(x)、valueArrayClass.isInstance(x)等
【讨论】:
Java 12 引入arrayType()
String.class.arrayType() == String[].class;
【讨论】: