我需要在Java中进行一些反射方法调用。这些调用将包含具有基本类型(int,double等)的参数的方法。在反复查找方法时指定这些类型的方法是int.class,double.class等。
挑战在于我接受来自外部源的输入,该源将动态指定类型。因此,我还需要动态地提出这些类引用。想象一个带有分隔文件的方法名列表,其中包含参数类型列表:
doSomething int double
doSomethingElse java.lang.String boolean
如果输入类似于java.lang.String
,我知道我可以将Class.forName("java.lang.String")
用于该类实例。有没有办法使用该方法或其他方法来获取原始类型Classes?
修改
感谢所有受访者。很明显,没有内置的方法来干净地做我想要的事情,所以我将决定重用Spring框架中的ClassUtils
类。它似乎包含Class.forName()的替代品,可以满足我的要求。
答案 0 :(得分:26)
原始类型的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
答案 1 :(得分:20)
Spring框架包含一个实用程序类ClassUtils,它包含静态方法forName。此方法可用于您描述的确切目的。
如果您不喜欢依赖Spring:可以找到source code of the method e。 G。 here 在他们的公共存储库中。类源代码是在Apache 2.0模型下许可的。
但请注意,该算法使用原始类型的硬编码映射。
编辑:感谢评论员DávidHorváth和Patrick指出了断开的链接。
答案 2 :(得分:17)
可能你只需要映射基元,其余的类执行“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 );
}
也就是说,创建一个存储基元类型的映射,如果描述属于基元,则使用映射的类。此映射也可以从外部配置文件加载,以增加灵活性,因此您可以将String添加为内置而不是java.lang.String,或者可能具有这样的方法。
“doSomething string yes | no”
在OS项目中有很多这样的代码,比如Struts,Hibernate,Spring和Apache库(仅举几例),所以你不需要从零开始。
顺便说一句。我没有编译上面的代码,但我很确定它只需要很少的修改就可以了。不要为此投票。
答案 3 :(得分:5)
答案 4 :(得分:3)
不幸的是,许多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;
}
答案 5 :(得分:2)
以下代码讨论了如何获取已知字段名称的基本类型的类,例如在这种情况下'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}
}
}
}
答案 6 :(得分:1)
Google Guava为此类内容提供了com.google.common.primitives.Primitives
。
答案 7 :(得分:0)
您可以使用以下代码:)
var polygon = require('./app1')({"xxxx": "zzzzz"}, yyyy);