动态查找表示原始 Java 类型的类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/180097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 10:58:58  来源:igfitidea点击:

Dynamically find the class that represents a primitive Java type

javareflectiontypesprimitive

提问by Mike Furtak

I need to make some reflective method calls in Java. Those calls will include methods that have arguments that are primitive types (int, double, etc.). The way to specify such types when looking up the method reflectively is int.class, double.class, etc.

我需要在 Java 中进行一些反射方法调用。这些调用将包括具有原始类型(int、double 等)参数的方法。反射式查找方法时指定此类类型的方法是 int.class、double.class 等。

The challenge is that I am accepting input from an outside source that will specify the types dynamically. Therefore, I need to come up with these Class references dynamically as well. Imagine a delimited file a list of method names with lists of parameter types:

挑战在于我正在接受来自外部来源的输入,该输入将动态指定类型。因此,我还需要动态地提出这些类引用。想象一个带参数类型列表的方法名称列表的分隔文件:

doSomething int double
doSomethingElse java.lang.String boolean

If the input was something like java.lang.String, I know I could use Class.forName("java.lang.String")to that Class instance back. Is there any way to use that method, or another, to get the primitive type Classes back?

如果输入类似于java.lang.String,我知道我可以使用Class.forName("java.lang.String")该 Class 实例。有什么方法可以使用该方法或其他方法来获取原始类型类?

Edit:Thanks to all the respondents. It seems clear that there is no built-in way to cleanly do what I want, so I will settle for reusing the ClassUtilsclass from the Spring framework. It seems to contain a replacement for Class.forName() that will work with my requirements.

编辑:感谢所有受访者。很明显,没有内置的方法可以干净利落地做我想做的事,所以我将满足于重用ClassUtilsSpring 框架中的类。它似乎包含 Class.forName() 的替代品,可以满足我的要求。

采纳答案by Synoli

The Spring framework contains a utility class ClassUtilswhich contains the static method forName. This method can be used for the exact purpose you described.

Spring 框架包含一个实用程序类ClassUtils,其中包含用于Name的静态方法。此方法可用于您描述的确切目的。

In case you don't like to have a dependency on Spring: the source code of the methodcan be found e.?g. hereon their public repository. The class source code is licensed under the Apache 2.0 model.

如果您不喜欢依赖 Spring:可以找到该方法源代码,例如 了这里对他们的公共仓库。类源代码在 Apache 2.0 模型下获得许可。

Note however that the algorithm uses a hard-coded map of primitive types.

但是请注意,该算法使用原始类型的硬编码映射。



Edit:Thanks to commenters Dávid Horváth and Patrick for pointing out the broken link.

编辑:感谢评论者 Dávid Horváth 和 Patrick 指出断开的链接。

回答by Daniel Spiewak

The Classinstances for the primitive types are obtainable as you said using e.g. int.class, but it is also possible to get the same values using something like Integer.TYPE. Each primitive wrapper class contains a static field, TYPE, which has the corresponding primitive class instance.

Class原始类型的实例可以如您所说的使用 eg 获得int.class,但也可以使用类似的方法获得相同的值Integer.TYPE。每个原始包装类都包含一个静态字段TYPE,该字段具有相应的原始类实例。

You cannot obtain the primitive class via forName, but you can get it from a class which is readily available. If you absolutely must use reflection, you can try something like this:

您无法通过 获取原始类forName,但可以从现成的类中获取它。如果你绝对必须使用反射,你可以尝试这样的事情:

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

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

回答by OscarRyz

Probably you just need to map the primitives and for the rest of the classes perform the "forName" method:

可能您只需要映射原语,其余类执行“forName”方法:

I would do something like:

我会做这样的事情:

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's 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 );
}

That is, create a map where the primitives types are stored and if the description belong to a primitive then use the mapped class. This map may also be loaded from an external configuration file, to add flexibility so you add String as a built in instead of java.lang.String or potentially have method like this.

也就是说,创建一个存储基元类型的映射,如果描述属于基元,则使用映射的类。该映射也可以从外部配置文件加载,以增加灵活性,因此您可以将 String 作为内置而不是 java.lang.String 添加,或者可能具有这样的方法。

"doSomething string yes|no "

"doSomething 字符串是|否"

There are lots of this kind of code in OS projects like Struts, Hibernate, Spring and Apache libs ( just to mention a few ) , so you don't need to start from zero.

像 Struts、Hibernate、Spring 和 Apache libs(仅举几例)这样的 OS 项目中有很多此类代码,因此您无需从零开始。

BTW. I did not compile the above code, but I'm pretty sure it works with little modifications don't down vote me for that.

顺便提一句。我没有编译上面的代码,但我很确定它只需稍作修改就可以工作,不要为此投票给我。

回答by Peter Lawrey

A number of Class methods don't handle primitives in a consistent fashion unfortunately. A common way around this in forName is to have a table like;

不幸的是,许多 Class 方法不能以一致的方式处理原语。在 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;
}

回答by Arham

The following code talks about how to get the class of a primitive type who's field name is known, e.g. in this case 'sampleInt'.

以下代码讨论了如何获取字段名称已知的原始类型的类,例如在本例中为“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;
    }
}

One can also check whether a given value is primitive or not by getting it's respective wrapper class or it's field value.

还可以通过获取其各自的包装类或字段值来检查给定值是否为原始值。

    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}
            }
        }
    }

回答by thSoft

Apache Commons Langhas ClassUtils.getClass(String), which supports primitive types.

Apache Commons LangClassUtils.getClass(String),它支持原始类型。

回答by Adrodoc55

Google Guava offers com.google.common.primitives.Primitivesfor this sort of stuff.

谷歌番石榴提供com.google.common.primitives.Primitives这类东西。

回答by LSafer SE

You can use this code :)

您可以使用此代码:)

/**
 * Get an array class of the given class.
 *
 * @param klass to get an array class of
 * @param <C>   the targeted class
 * @return an array class of the given class
 */
public static <C> Class<C[]> arrayClass(Class<C> klass) {
    return (Class<C[]>) Array.newInstance(klass, 0).getClass();
}

/**
 * Get the class that extends {@link Object} that represent the given class.
 *
 * @param klass to get the object class of
 * @return the class that extends Object class and represent the given class
 */
public static Class<?> objectiveClass(Class<?> klass) {
    Class<?> component = klass.getComponentType();
    if (component != null) {
        if (component.isPrimitive() || component.isArray())
            return Reflect.arrayClass(Reflect.objectiveClass(component));
    } else if (klass.isPrimitive()) {
        if (klass == char.class)
            return Character.class;
        if (klass == int.class)
            return Integer.class;
        if (klass == boolean.class)
            return Boolean.class;
        if (klass == byte.class)
            return Byte.class;
        if (klass == double.class)
            return Double.class;
        if (klass == float.class)
            return Float.class;
        if (klass == long.class)
            return Long.class;
        if (klass == short.class)
            return Short.class;
    }

    return klass;
}

/**
 * Get the class that don't extends {@link Object} from the given class.
 *
 * @param klass to get the non-object class of
 * @return the non-object class of the given class
 * @throws IllegalArgumentException when the given class don't have a primitive type
 */
public static Class<?> primitiveClass(Class<?> klass) {
    if (klass == Character.class)
        return char.class;
    if (klass == Integer.class)
        return int.class;
    if (klass == Boolean.class)
        return boolean.class;
    if (klass == Byte.class)
        return byte.class;
    if (klass == Double.class)
        return double.class;
    if (klass == Float.class)
        return float.class;
    if (klass == Long.class)
        return long.class;
    if (klass == Short.class)
        return short.class;

    throw new IllegalArgumentException(klass + " don't have a primitive type");
}