最近研究jetty源代碼的時候,發(fā)現(xiàn)這個容器里面的代碼根本無法看懂,都是java語法,基本上都是反射+設(shè)計模式+配置文件。很莫名奇妙的方法調(diào)用。里面有調(diào)用main方法的反射,結(jié)果沒看懂,所以就再來研究研究反射功能。由于反射的文章在網(wǎng)上太多了,我主要研究了一下main方法,private方法的調(diào)用。如下,反射調(diào)用HelloWorld類的方法。HelloWorld類如下:
調(diào)用main方法如下:
1 調(diào)用main方法需要注意,main方法的參數(shù)為String[],但是在method.invoke時,需要將String[]強制轉(zhuǎn)換為Object,至于原因,網(wǎng)上很多說這個,主 要是說jdk執(zhí)行main方法時要將String[]分成多個參數(shù)等等。后續(xù)我分析了源代碼后,會將這個問題專門寫個文章出來。
2 調(diào)用private方法需要注意,在調(diào)用此方法之前,需要將此執(zhí)行的方法設(shè)置以下,而不是隨便找個地方運行下method.setAccessible(true)就完事了。
3 使用反射動態(tài)調(diào)用方法時,主要是用method.invoke()方法,如果是靜態(tài)方法,則invoke的第一個參數(shù)設(shè)置null,如果不是靜態(tài)方法,則將第一個參數(shù)設(shè) 置為該類生成的對象即可。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
private void prt(String msg){
System.out.println(msg);
}
}
public static void main(String[] args) {
System.out.println("HelloWorld");
}
private void prt(String msg){
System.out.println(msg);
}
}
調(diào)用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[]{});
}
}
調(diào)用private方法如下: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[]{});
}
}
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");
}
}
}
}
總結(jié):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 調(diào)用main方法需要注意,main方法的參數(shù)為String[],但是在method.invoke時,需要將String[]強制轉(zhuǎn)換為Object,至于原因,網(wǎng)上很多說這個,主 要是說jdk執(zhí)行main方法時要將String[]分成多個參數(shù)等等。后續(xù)我分析了源代碼后,會將這個問題專門寫個文章出來。
2 調(diào)用private方法需要注意,在調(diào)用此方法之前,需要將此執(zhí)行的方法設(shè)置以下,而不是隨便找個地方運行下method.setAccessible(true)就完事了。
3 使用反射動態(tài)調(diào)用方法時,主要是用method.invoke()方法,如果是靜態(tài)方法,則invoke的第一個參數(shù)設(shè)置null,如果不是靜態(tài)方法,則將第一個參數(shù)設(shè) 置為該類生成的對象即可。