2013-04-25 139 views
2

嗨,我正在使用反射來實現某些功能。 我已經給出了類名,該類的方法名和需要傳遞給文件中該方法的參數值(取任何文件,不是約束)。 我必須用參數調用該方法。此方法不返回任何內容。 這個類有一個巨大的方法列表,每個方法的參數列表各不相同。並且我也有不同的排列和組合。 那麼我怎麼能做到這一點。 我曾嘗試用不同的開關子句對硬件進行硬編碼,但它是一個真正的開銷和風險的事情來維護。 我們是否可以動態地做這件事,就像在飛行中從文件中讀取方法名稱及其參數並調用它。 任何小代碼片段都會有所幫助。 TIA。如何將多個參數傳遞給java反射中的某個方法

+0

使用對象[] {PAR1,PAR2,..} – BlackJoker 2013-04-25 05:50:40

+1

記住,有StackOverflow的格式,你需要按輸入_twice_。 – Zyerah 2013-04-25 05:50:50

+0

你可以分享方法參數的排列組合嗎? – Apurv 2013-04-25 05:51:54

回答

6

大家好我找到了解決上述問題的方法。下面是示例代碼片段。

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

我希望這也能幫助別人。

+1

供參考:您通過在每行的前面添加四個空格來格式化代碼;) – Tobber 2013-10-19 20:14:46

+0

@Bittenus我只是通過選擇代碼行來按Ctrl + K來格式化代碼。這是代碼格式警告提示,以格式化代碼。反正從下次我會確定。謝謝 – 2013-10-20 14:24:10

+0

謝謝你,我對Java很有新意,我爲此苦苦掙扎,只有一個問題。爲什麼你使用Integer.Type而不是.class? – 2016-01-13 20:00:49

2
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中的一個新特性,但我已經看到您現在可以使用參數調用,而不是使用數組,這可能會使您的代碼更好地閱讀(這是另一種方式)。如果您需要可變數量的參數,並且事先不知道會有多少個參數,那麼分配數組的操作就會失敗,並且應該也是向後兼容的。

相關問題