最近研究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,如果不是静态方法,则将第一个参数设置为该类生成的对象即可。