dynamic查找代表原始Javatypes的类
我需要在Java中进行一些reflection方法调用。 这些调用将包括具有基本types(int,double等)参数的方法。 在查找方法时,指定这种types的方法是int.class,double.class等。
我面临的挑战是我接受来自外部来源的input,将dynamic地指定types。 因此,我也需要dynamic地创build这些类引用。 设想一个分隔文件的方法名称列表,其中包含参数types列表:
doSomething int double doSomethingElse java.lang.String boolean
如果input类似java.lang.String
,我知道我可以使用Class.forName("java.lang.String")
到该类实例。 有什么方法可以使用该方法或其他方法来获取原始types类?
编辑:感谢所有的受访者。 看起来很清楚,没有内build的方法来干净地做我想做的事情,所以我将决定重用Spring框架中的ClassUtils
类。 它似乎包含一个替代Class.forName(),将符合我的要求。
Spring框架包含一个包含静态方法forName的实用程序类ClassUtils 。 这种方法可以用于你描述的确切目的。
如果你不喜欢Spring的依赖:可以find方法的源代码 。 G。 这里在他们的公共存储库。 类源代码在Apache 2.0模型下获得许可。
但请注意,algorithm使用原始types的硬编码映射。
编辑:感谢评论者DávidHorváth和Patrick指出断开的链接。
基本types的Class
实例可以像使用例如int.class
,但是也可以使用像Integer.TYPE
一样的方式获得相同的值。 每个原始包装类都包含一个静态字段TYPE
,它具有相应的原始类实例。
你不能通过forName
获得原始类,但是你可以从一个容易获得的类中获得它。 如果你绝对必须使用reflection,你可以尝试这样的事情:
Class clazz = Class.forName("java.lang.Integer"); Class intClass = clazz.getField("TYPE").get(null); intClass.equals(int.class); // => true
可能你只需要映射原语,其余的类都执行“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'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 ); }
也就是说,创build一个映射,其中存储基元types,如果描述属于一个基元,则使用映射的类。 这个映射也可以从外部configuration文件加载,以增加灵活性,所以你添加string作为内置的而不是java.lang.String或可能有这样的方法。
“doSomethingstring是|否”
在Struts,Hibernate,Spring和Apache libs等操作系统项目中有很多这样的代码(只是提到一些),所以你不需要从零开始。
BTW。 我没有编译上面的代码,但我很确定它的工作与一点修改不投票给我。
Apache Commons Lang有ClassUtils.getClass(String) ,它支持原始types。
许多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; }
下面的代码讨论了如何获取字段名称已知的基本types的类,例如在本例中是'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} } } }
谷歌Guava提供com.google.common.primitives.Primitives
这种东西。