Получение массива Class типа компонента - PullRequest
41 голосов
/ 04 февраля 2011

Если у меня есть экземпляр Class, есть ли способ получить экземпляр Class для его типа массива? По сути, я прошу эквивалент метода getArrayType, обратного методу getComponentType(), такого, что:

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

Ответы [ 4 ]

49 голосов
/ 04 февраля 2011

Одна вещь, которая приходит в голову:

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());

Документация Class#getName() строго определяет формат имен классов массивов:

Если этот объект класса представляет класс массивов, то внутренняя форма имени состоит из имени типа элемента, которому предшествует один или несколько символов '[', представляющих глубину вложения массива.

Подход Class.forName(..) не будет работать напрямую для примитивов - для них вам придется создать отображение между именем (int) и сокращением массива - (I)

12 голосов
/ 04 марта 2014

На самом деле из-за 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);
}
7 голосов
/ 04 февраля 2011

Вы можете сделать следующее

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

Обычно вам не нужно знать тип, вы просто хотите создать массив.

2 голосов
/ 15 сентября 2011

Другим возможным рефакторингом является использование универсального суперкласса и передача в конструктор двух объектов класса.

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) и т. д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...