最近研究jetty源代碼的時候,發現這個容器裏面的代碼根本無法看懂,都是java語法,基本上都是反射+設計模式+配置文件。很莫名奇妙的方法調用。裏面有調用main方法的反射,結果沒看懂,所以就再來研究研究反射功能。由於反射的文章在網上太多了,我主要研究了一下main方法,private方法的調用。如下,反射調用HelloWorld類的方法。HelloWorld類如下:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
private void prt(String msg){
System.out.println(msg);
}
}
調用main方法如下:
public class HelloWorldRefection {
public static void main(String[] args) throws InstantiationException, IllegalAccessException,
SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
Method method = HelloWorld.class.getMethod("main",String[].class);
method.invoke(null,(Object)new String[]{});
}
}
調用private方法如下:
public class HelloWorldRefection {
public static void main(String[] args) throws InstantiationException, IllegalAccessException,
SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
Class clazz = HelloWorld.class;
HelloWorld helloworld = HelloWorld.class.newInstance();
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
if(method.getName().equals("prt")){
method.setAccessible(true);
method.invoke(helloworld, "hello");
}
}
}
}
總結:
1 調用main方法需要注意,main方法的參數爲String[],但是在method.invoke時,需要將String[]強制轉換爲Object,至於原因,網上很多說這個,主要是說jdk執行main方法時要將String[]分成多個參數等等。後續我分析了源代碼後,會將這個問題專門寫個文章出來。
2 調用private方法需要注意,在調用此方法之前,需要將此執行的方法設置以下,而不是隨便找個地方運行下method.setAccessible(true)就完事了。
3 使用反射動態調用方法時,主要是用method.invoke()方法,如果是靜態方法,則invoke的第一個參數設置null,如果不是靜態方法,則將第一個參數設置爲該類生成的對象即可。