嗨,我使用反射来实现的东西。 我一直在给定的类名,需要被传递到一个文件中的方法(以任意文件。不是约束)该类别和参数值的方法名。 我要打电话与参数方法。 此方法不返回任何东西。 有一个巨大的在这个类和参数的变化每个列表方法列表。
例如: method1(String, String, int, boolean)
method1(String, int, boolean)
,并且同样我有不同的排列和组合。 那么,如何才能做到这一点。 我曾尝试硬编码的事情用不同的开关条款,但它是一个真正的开销和维护风险的事情。 我们可以动态地做这件事情,就像在飞行阅读方法名,并从文件的参数,并调用它。 任何一个小的代码段会有所帮助。 TIA。
大家好我已经找到了解决上述问题。 下面是示例代码片段。
package reflections;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectionTest {
public void method1(String str, int number) {
System.out.println(str + number);
}
public void method1(String str) {
System.out.println(str);
}
public void method1() {
System.out.println("helloworld");
}
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException, IllegalArgumentException,
InvocationTargetException {
// Step 1) Make an object array and store the parameters that you wish
// to pass it.
Object[] obj = {};// for method1()
// Object[] obj={"hello"}; for method1(String str)
// Object[] obj={"hello",1}; for method1(String str,int number)
// Step 2) Create a class array which will hold the signature of the
// method being called.
Class<?> params[] = new Class[obj.length];
for (int i = 0; i < obj.length; i++) {
if (obj[i] instanceof Integer) {
params[i] = Integer.TYPE;
} else if (obj[i] instanceof String) {
params[i] = String.class;
}
// you can do additional checks for other data types if you want.
}
String methoName = "method1"; // methodname to be invoked
String className = "reflections.ReflectionTest";// Class name
Class<?> cls = Class.forName(className);
Object _instance = cls.newInstance();
Method myMethod = cls.getDeclaredMethod(methoName, params);
myMethod.invoke(_instance, obj);
}
}
我希望这会帮助别人了。
public class ReflectionSample
{
private Object mString = null;
private int mValue;
public ReflectionSample()
{
}
public ReflectionSample(int oValue)
{
mValue = oValue;
}
public ReflectionSample(String oString)
{
mString = oString;
}
public ReflectionSample(String oString, int oValue)
{
setValues(oString, oValue);
}
public void setValues(String oString, int oValue)
{
mString = oString;
mValue = oValue;
}
public String toString()
{
return ""+mString+":"+mValue;
}
public void run()
{
String oInput = "Teststring";
Class<?> cls;
String clsname = "main.ReflectionSample";
Object rs = null; // ReflectionSample
Object rsc = null;
System.out.println(this.getClass().getName());
try
{
System.out.println(clsname);
cls = Class.forName(clsname);
if(cls == null)
{
System.err.println(clsname + " doesn't exist");
return;
}
// Look for a constructor which has a single string
Constructor<?> ct = null;
Class<?>[] param_types = new Class<?>[1];
Object[] arguments = new Object[1];
param_types[0] = String.class;
// get the string constructor
ct = cls.getConstructor(param_types);
// We only have one object
arguments = new Object[1];
arguments[0] = oInput;
// Instantiate the object with passed in argument.
rs = ct.newInstance(arguments);
System.out.println("String constructor sample: "+rs);
// Instantiate with default constructor
param_types = new Class<?>[0];
arguments = new Object[0];
ct = cls.getConstructor(param_types);
rs = ct.newInstance(arguments);
rsc = rs; // Keep it for later, to lazy to call it again
System.out.println("Default constructor sample: "+rs);
// Instantiate with string and int constructor
param_types = new Class<?>[2];
arguments = new Object[2];
// Must be in the same order as the params I think
param_types[0] = String.class;
param_types[1] = Integer.TYPE; // <-- Its a primitive so use TYPE not Class
arguments[0] = oInput;
arguments[1] = new Integer(1);
ct = cls.getConstructor(param_types);
rs = ct.newInstance(arguments);
System.out.println("String plus int constructor sample: "+rs);
// call the setValues method
param_types[0] = String.class;
param_types[1] = Integer.TYPE; // <-- Its a primitive so use TYPE not Class
arguments[0] = oInput;
arguments[1] = 1;
System.out.println("setValues invocation before: "+rsc);
Method m = cls.getMethod("setValues", param_types);
m.invoke(rsc, arguments);
System.out.println("setValues invocation after: "+rsc);
// An alternative method to pass the parameters
m = cls.getMethod("setValues", String.class, Integer.TYPE);
m.invoke(rsc, oInput+"x", 2);
System.out.println("setValues invocation after: "+rsc);
}
catch(Throwable e)
{
System.err.println(e.getLocalizedMessage());
}
}
}
输出:
main.ReflectionSample
main.ReflectionSample
String constructor sample: Teststring:0
Default constructor sample: null:0
String plus int constructor sample: Teststring:1
setValues invocation before: null:0
setValues invocation after: Teststring:1
希望这可以帮助。
我不知道这是在Java中的新功能,但我已经看到了,你现在可以使用调用与参数为好,而不是使用数组,这可能使你的代码更好的阅读(这是另一种方法) 。 如果你需要一个可变数量的参数,你不事先知道多少会有,分配阵列defeinitly工作,也应该是backwardcompatible。
一个简单的解决方案是创建一个Class
与需要被传递的参数:
public class ObjectArguments {
private PrintWriter out;
private String productId;
private int action;
public ObjectArguments(PrintWriter out, String productId, int action) {
this.out = out;
this.productId = productId;
this.action = action;
}
public PrintWriter getOut() {
return out;
}
public String getProductId() {
return productId;
}
public int getAction() {
return action;
}
}
假设你要调用一个类Foo
与方法命名的bar
。
那就这样做。
PrintWriter out = null;
String productId = null;
int action = 0;
Class[] paramArguments = new Class[1];
paramArguments[0] = ObjectArguments.class;
ObjectArguments newObj = new ObjectArguments(out,productId,action);
Class cls = Class.forName("Foo");
Object obj = cls.newInstance();
Method method = cls.getDeclaredMethod("bar", paramArguments);
method.invoke(obj, newObj);