Как получить класс примитивных типов с помощью Javassist?

В моей программе я имею дело с классами и примитивными типами. Если программа находит класс, она просто выполняет один из следующих вызовов:

  • Class.forName(classname)
  • cc.toClass() где cc является экземпляром CtClass

Однако, если он находит примитивный тип, все становится еще хуже:

  • Class.forName нельзя использовать, его нельзя использовать с примитивными типами.
  • cc.toClass() возвращает null

Можно вызвать поле TYPE из класса-оболочки примитивных типов, но как это сделать с помощью отражения?

Вот мой код:

CtClass cc;//Obtained from caller code
Class<?> classParam;
if (cc.isprimitive()) {
    classParam= ?? // How can I get TYPE field value with reflection ?
} else {
    String nomClasseParam = cc.getName();

    if (nomClasseParam.startsWith("java")) {
        classeParam = Class.forName(nomClasseParam);
    } else {
        classeParam = cc.toClass();
    }
 }

Javasist 3.12.0.GA

EDIT: я разместил решение, которое я выбрал в ответах ниже. Во всяком случае, я отметил ответ Тома.


person Stephan    schedule 12.09.2011    source источник
comment
Этот другой вопрос определенно поможет: boolean.class ?   -  person Andreas Dolk    schedule 12.09.2011
comment
@Andreas_D Не так много, так как я хочу выполнить вызов с отражением Java.   -  person Stephan    schedule 12.09.2011
comment
но мы можем использовать boolean.class, int.class и т. д. как объекты Class, когда отражаем методы и конструкторы   -  person Andreas Dolk    schedule 12.09.2011
comment
С образцом кода в вопросе, как я могу его достичь?   -  person Stephan    schedule 12.09.2011
comment
Этот вопрос на самом деле не об отражении, а о javassist. Вопрос в том, как мы можем перейти от экземпляра CtClass к экземпляру Class.   -  person Tom Anderson    schedule 12.09.2011


Ответы (3)


Мне кажется, что вы можете привести cc к его подклассу CtPrimitiveType.

Если вам нужна оболочка, вы можете использовать метод getWrapperName, чтобы получить имя класса соответствующей оболочки. Вы можете использовать Class.forName, как обычно, чтобы превратить это имя в объект Class. Однако я не думаю, что вам нужна обертка, так что это не поможет.

Вместо этого, я думаю, вам нужен getDescriptor, за которым следует кропотливо написанный вручную оператор switch:

switch(descriptor) {
    case 'I': classParam = int.class; break;
    // etc
}

Что-то подобное действительно должно быть в Javassist. Но насколько я вижу, это не так.

person Tom Anderson    schedule 12.09.2011
comment
Наконец, я использую getWrapperName и мне не нужно кодировать оператор switch. - person Stephan; 12.09.2011
comment
Учитывая, что существует всего восемь примитивных типов, написать этого будет несложно. - person Tom Anderson; 12.09.2011

Основываясь на ответах Тома и Момо, я придумал следующее решение:

CtClass cc; //Obtained from caller code
Class<?> classParam;

if (cc.isprimitive()) {
    classParam = Class.forName(((CtPrimitiveType)cc).getWrapperName());
    classParam = (Class<?>)classParam.getDeclaredField("TYPE").get( classParam );
} else {
    String nomClasseParam = cc.getName();

    if (nomClasseParam.startsWith("java")) {
        classeParam = Class.forName(nomClasseParam);
    } else {
        classeParam = cc.toClass();
    }
 }

Я вызываю метод CtPrimitiveType#getWrapperName, а затем использую поле TYPE для получения класса примитивного типа. Я также избегаю написания оператора switch.

Спасибо за помощь ребята.

person Stephan    schedule 12.09.2011

Вы можете сделать Class.forName для оболочки объекта примитива (например, Integer для примитива int). Java поддерживает автоупаковку, поэтому вы можете обмениваться между оболочкой Object и примитивным аналогом.

Я предполагаю, что вы используете CtClass из JavaAssist. Если cc является примитивом, я думаю, что это будет тип CtPrimitiveType (необходимо подтвердить), и в этом случае вы можете использовать и вызывать getWrapperName(), чтобы получить класс-оболочку.

person momo    schedule 12.09.2011
comment
Неправда в мире отражений. :( - person dacwe; 12.09.2011
comment
Вы правы, Java поддерживает автоупаковку, но класс, с которым я работаю, динамически генерируется Javassist. Сгенерированный класс имеет метод с параметром int. Загрузчик классов не сможет найти этот метод, если я передам ему параметр java.lang.Integer в Class.forName. - person Stephan; 12.09.2011
comment
@dawce Argh, я этого не знал :( Нужно больше играть с отражением. Стефан выглядит так, что ответ Тома должен сработать. - person momo; 12.09.2011
comment
cc является типом CtPrimitiveType. я проверю getWrapperName - person Stephan; 12.09.2011