類Target.java有一個execute()方法,用一個String數組做爲參數java
public class Target { public void execute(String[] args) { System.out.println("call execute method with parameter type String[]"); } }
用以下方式,經過反射去調用這個方法數組
public class Test { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { String[] parameters = {"1"}; // parameter array Class targetClass = Class.forName("Target");// get target class "Target" Object instance= targetClass.newInstance(); Method execute = targetClass.getDeclaredMethod("execute", String[].class);// get target method "execute" execute.invoke(instance, parameters);// invoke method } }
結果控制檯出現報錯code
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at Test.main(Test.java:16)get
找到Method.invoke方法,其實它接收的是一個變長參數(Varargs)。編譯器
public Object invoke(Object obj, Object... args)it
當編譯器發現相似io
method.invoke(object, arg1, arg2)編譯
這樣的表示時,會隱式地建立一個數組,相似new Object [] {arg1, arg2},而後將該數組做爲invoke方法的參數。 可是若是目標方法的參數原本就是一個數組的時候,如class
method.invoke(object, Object[])thread
編譯器會認爲你已經將全部的參數放到數組裏面了,從而不會再次包裝。因而在這種狀況下,做爲參數傳遞給目標方法的,實際上是數組裏面的元素,而不是數組自己。
因此咱們來回看上面的例子,其實main方法最終經過反射嘗試調用的是,以一個String類型做爲參數的execute方法,咱們來作個試驗
public class Target { public void execute(String[] args) { System.out.println("call execute method with parameter type String[]"); } public void execute(String arg) { System.out.println("call execute method with parameter type String"); } } public class Test { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { String[] parameters = {"1"}; // parameter array Class targetClass = Class.forName("Target");// get target class "Target" Object instance= targetClass.newInstance(); Method execute = targetClass.getDeclaredMethod("execute", String.class);// get target method "execute" execute.invoke(instance, parameters);// invoke method } }
最終打印出來的是(注意兩個方法參數是不同的)
call execute method with parameter type String
其實這種狀況的解決方法很簡單,只要把數組包裝成Object數組的第一個元素就行了,這樣編譯器就會把數組自己做爲參數,傳遞給目標方法了,以下:
public class Test { public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { String[] parameters = {"1"}; // parameter array Class targetClass = Class.forName("Target");// get target class "Target" Object instance = targetClass.newInstance(); Method execute = targetClass.getDeclaredMethod("execute", String[].class);// get target method "execute" execute.invoke(instance, new Object[] {parameters});// invoke method } }
當用反射調用方法時,若是目標方法的入參是一個數組,則要把數組包裝到另外一個Object數組中。