写Method方法后,再来搞定反射构造方法,当然可能要被很多正规出书的人嗤之以鼻,但是这一切都不重要,重要的是,对于一个初学者,以本人自己学习的过程,颠倒的来写,会让人更容易接受一些.
同样的,给出Constructor类的几个API :
newInstance(Object... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
|
初始化一个类实例的时候调用,参数和实际构造方法里面参数个数和参数类型保持一致的传递. |
Int getParameterCount() |
偶尔可以用这个方法查一下当前构造方面是带了几个参数的. |
http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Constructor.html |
好了,其实API还要好几个,有需要的读者,可以参考下面的链接,查看.
下面,继续做程序,做测试,看看上面的如何使用.
<1> : 新建一个java工程,目录树如下 :
<2> : 新建一个被测试的类FlexClass.java,如下 :
/** * */ package com.oneplus.flex; /** * @author zhibao.liu * @date 2015-11-18 * @company : oneplus.Inc */ public class FlexClass { private int days; private String name; private char a; private int month; private int year; private String msg; public FlexClass() { msg = "here is zhibao.liu in oneplus.Inc!"; } public FlexClass(char a, String name, int days) { this.a = a; this.name = name; this.days = days; } public FlexClass(int year) { this.year = year; } public FlexClass(int month, String name) { this.month = month; this.name = name; } public FlexClass(String msg) { this.msg = msg; } private int Add(){ return month+year; } private void showName(){ System.out.println("Name : "+name); } private void showMsg(){ System.out.println("message : "+msg); } }
我在上面写了5个不同的构造方法,现在你先看看通过反射列举所有的构造和及其参数个数,在主类中增加代码如下 :
private static void OneplusConstructorFlex(String packagename){ try { Class clazz=Class.forName(packagename); try { Object obj=clazz.newInstance(); Constructor[] constructs=clazz.getDeclaredConstructors(); for(int i=0;i<constructs.length;i++){ System.out.println("Constructor "+i+" parameter count : "+constructs[i].getParameterCount()); } } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
得到的结果如下:
下面来看一看具体使用,在主类中再增加一个方法:
private static void OneplusUsingConstructorFlex(String packagename){ try { Class clazz=Class.forName(packagename); try { Constructor constructor=clazz.getDeclaredConstructor(new Class[]{int.class,String.class}); try { Object obj=constructor.newInstance(new Object[]{12,"I am zhibao.liu !!!"}); Method method=clazz.getDeclaredMethod("showName", new Class[]{}); method.setAccessible(true); method.invoke(obj, new Object[]{}); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
程序大概讲解 :
<1> :Constructor constructor=clazz.getDeclaredConstructor(new Class[]{int.class,String.class});
这一步很显然制定了,获取带两个参数的构造方法,其中构造方法第一个参数是int型,第二个位String型,这样一步就确定了获取制定的构造方法进行实例化.
<2> : Object obj=constructor.newInstance(new Object[]{12,"I am zhibao.liu !!!"});
根据上面制定的构造方法,进行实例化的时候传入指定数据类型的参数值.
<3> : 经过上面两部,就完全确定了反射出来的类使用的是哪一个构造方法实例化出来的.
<4> : 然后:
Method method=clazz.getDeclaredMethod("showName", new Class[]{}); method.setAccessible(true); method.invoke(obj, new Object[]{});
通过这一段来验证构造时传入的参数是否存在有效了,继续反射一个方法出来(这就是为什么先讲如何反射方法的原因),然后看看下面的结果:
正是前面构造的时候传入的.
从上面,我们以此类推,掌握其他的构造方式的使用.