Получение массива Класс типа компонента
Если у меня есть экземпляр Class
, существует ли способ получить экземпляр Class
для его типа массива? То, что я по существу прошу, эквивалентно методу getArrayType
, который является обратным методу getComponentType()
, так что:
array.getClass().getComponentType().getArrayType() == array.getClass()
Ответы
Ответ 1
Одна вещь, которая приходит на ум:
java.lang.reflect.Array.newInstance(componentType, 0).getClass();
Но он создает ненужный экземпляр.
Btw, это работает:
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());
Документация Class#getName()
строго определяет формат имен классов массива:
Если этот объект класса представляет класс массивов, то внутренняя форма имени состоит из имени типа элемента, которому предшествует один или несколько символов [[], представляющих глубину вложенности массива.
Подход Class.forName(..)
не будет работать напрямую для примитивов, но для них вам нужно будет создать сопоставление между именем (int
) и сокращением массива - (I
)
Ответ 2
На самом деле из-за 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);
}
Ответ 3
Вы можете сделать следующее
array.getClass() ==
Array.newInstance(array.getClass().getComponentType(), 0).getClass()
Обычно вам не нужно знать тип, вы просто хотите создать массив.
Ответ 4
Еще один возможный рефакторинг - использовать общий суперкласс и передать в объект класса два объекта.
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)
и т.д.