簡體   English   中英

如何在java反射中將多個參數傳遞給一個方法

[英]how to pass multiple parameters to a method in java reflections

嗨,我正在使用反射來實現某些目標。 我已經獲得了類名、該類的方法名以及需要在文件中傳遞給該方法的參數值(取任何文件。不是約束)。 我必須使用參數調用該方法。 此方法不返回任何內容。 此類中有大量方法列表,每個方法的參數列表各不相同。

例如: method1(String, String, int, boolean) method1(String, int, boolean)同樣我有不同的排列和組合。 那么我怎樣才能做到這一點。 我曾嘗試使用不同的 switch 子句對事物進行硬編碼,但這是一個真正的開銷和維護的風險。 我們可以動態地做這個事情,比如從文件中動態讀取方法名稱及其參數並調用它。 任何小的代碼片段都會有所幫助。 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 中較新的功能,但我已經看到您現在也可以使用帶參數的 invoke,而不是使用數組,這可能會使您的代碼更易於閱讀(這是另一種方式) . 如果您需要可變數量的參數並且您事先不知道會有多少個,那么分配數組肯定是有效的,並且也應該是向后兼容的。

一個簡單的解決方案是使用需要傳遞的參數創建一個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;
  }
}

假設您要使用名為bar的方法調用類Foo
然后它會像這樣完成。

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);

對於兩個 int 參數,示例如下,類似地,也可以調用其他數據類型參數

Method method=new Test1().getClass().getMethod(x, new Class[] {int.class,int.class});

我們可以調用一個需要 3 個參數int,int,string ,如下所示:

Method method=new Test1().getClass().getMethod(x, new Class[] {int.class,int.class, String.class});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM