Динамически найти класс, представляющий примитивный тип Java

Мне нужно сделать некоторые рефлексивные вызовы методов в Java. Эти вызовы будут включать методы, содержащие аргументы, которые являются примитивными типами (int, double и т.д.). Способ определения таких типов при поиске метода отражается в int.class, double.class и т.д.

Проблема заключается в том, что я принимаю вход от внешнего источника, который будет динамически определять типы. Поэтому мне также нужно динамически использовать эти описания классов. Представьте в файле с разделителями список имен методов со списками типов параметров:

doSomething int double
doSomethingElse java.lang.String boolean

Если вход был чем-то вроде java.lang.String, я знаю, что могу использовать Class.forName("java.lang.String") для экземпляра класса. Есть ли способ использовать этот метод или другое, чтобы вернуть примитивные типы классов?

Edit: Спасибо всем респондентам. Кажется очевидным, что нет встроенного способа чистого выполнения того, что я хочу, поэтому я соглашусь на повторное использование класса ClassUtils из фреймворка Spring. Кажется, он содержит замену Class.forName(), которая будет работать с моими требованиями.

Ответ 1

Структура Spring содержит класс утилиты ClassUtils, который содержит статический метод forName. Этот метод можно использовать для конкретной цели, которую вы описали.

Если вам не нравится зависимость от Spring: исходный код метода, можно найти e, г. здесь в своем публичном репозитории. Исходный код класса лицензируется в соответствии с моделью Apache 2.0.

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


Изменить: Спасибо комментаторам Dávid Horváth и Patrick за указание на неработающую ссылку.

Ответ 2

Экземпляры Class для примитивных типов можно получить, как вы сказали, используя, например, int.class, но также можно получить одинаковые значения, используя что-то вроде Integer.TYPE. Каждый примитивный класс-оболочка содержит статическое поле, TYPE, которое имеет соответствующий примитивный экземпляр класса.

Вы не можете получить примитивный класс через forName, но вы можете получить его из класса, который легко доступен. Если вы абсолютно должны использовать отражение, вы можете попробовать что-то вроде этого:

Class clazz = Class.forName("java.lang.Integer");
Class intClass = clazz.getField("TYPE").get(null);

intClass.equals(int.class);         // => true

Ответ 3

Возможно, вам просто нужно отобразить примитивы, а для остальных классов выполните метод "forName":

Я бы сделал что-то вроде:

void someWhere(){
     String methodDescription = "doSomething int double java.lang.Integer java.lang.String"
     String [] parts = methodDescription.split();
     String methodName= parts[0]
     Class [] paramsTypes = getParamTypes( parts ); // Well, not all the array, but a, sub array from 1 to arr.length..  

    Method m = someObject.class.getMethod( methodName, paramTypes );
    etc. etc etc.
}

public Class[] paramTypes( String [] array ){
     List<Class> list = new ArrayList<Class>();
     for( String type : array ) {
         if( builtInMap.contains( type )) {
             list.add( builtInMap.get( type ) );
          }else{
             list.add( Class.forName( type ) );
          }
     }
     return list.toArray();
}  

    // That right.
Map<String,Class> builtInMap = new HashMap<String,Class>();{
       builtInMap.put("int", Integer.TYPE );
       builtInMap.put("long", Long.TYPE );
       builtInMap.put("double", Double.TYPE );
       builtInMap.put("float", Float.TYPE );
       builtInMap.put("bool", Boolean.TYPE );
       builtInMap.put("char", Character.TYPE );
       builtInMap.put("byte", Byte.TYPE );
       builtInMap.put("void", Void.TYPE );
       builtInMap.put("short", Short.TYPE );
}

То есть, создайте карту, где хранятся типы примитивов, и если описание принадлежит примитиву, то используйте сопоставленный класс. Эта карта также может быть загружена из внешнего файла конфигурации, чтобы добавить гибкость, поэтому вы добавляете String как встроенную вместо java.lang.String или потенциально имеете такой метод.

"doSomething string yes | no"

В OS-проектах есть такие кодеки, как Struts, Hibernate, Spring и Apache libs (только для некоторых), поэтому вам не нужно начинать с нуля.

BTW. Я не компилировал вышеприведенный код, но я уверен, что он работает с небольшими изменениями, не проголосуйте за меня.

Ответ 5

Некоторые методы класса не относятся к примитивам непротиворечивым образом. Общим способом для этого в forName является наличие таблицы, например:

private static final Map<String, Class> BUILT_IN_MAP = 
    new ConcurrentHashMap<String, Class>();

static {
    for (Class c : new Class[]{void.class, boolean.class, byte.class, char.class,  
            short.class, int.class, float.class, double.class, long.class})
        BUILT_IN_MAP.put(c.getName(), c);
}

public static Class forName(String name) throws ClassNotFoundException {
    Class c = BUILT_IN_MAP.get(name);
    if (c == null)
        // assumes you have only one class loader!
        BUILT_IN_MAP.put(name, c = Class.forName(name));
    return c;
}

Ответ 6

Следующий код рассказывает о том, как получить класс примитивного типа, имя которого известно, например. в этом случае "sampleInt".

public class CheckPrimitve {
    public static void main(String[] args) {
        Sample s = new Sample();
        try {
            System.out.println(s.getClass().getField("sampleInt").getType() == int.class); // returns true
            System.out.println(s.getClass().getField("sampleInt").getType().isPrimitive()); // returns true
        } catch (NoSuchFieldException e) {          
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }       
    }
}

class Sample {
    public int sampleInt;
    public Sample() {
        sampleInt = 10;
    }
}

Можно также проверить, является ли данное значение примитивным или нет, получив соответствующий класс-оболочку или значение поля.

    public class CheckPrimitve {
        public static void main(String[] args) {
            int i = 3;
            Object o = i;
            System.out.println(o.getClass().getSimpleName().equals("Integer")); // returns true
            Field[] fields = o.getClass().getFields();
            for(Field field:fields) {
                System.out.println(field.getType()); // returns {int, int, class java.lang.Class, int}
            }
        }
    }

Ответ 7

Google Guava предлагает com.google.common.primitives.Primitives для такого рода материалов.