关于Java反射机制中通过getConstructors()方法获取类中全部构造方法顺序的问题
关于Java反射机制中通过getConstructors方法获取类中全部构造方法顺序的问题
近日学习java反射机制的过程中了解到的getConstructors()方法,此方法用于取得全部构造方法,在测试过程发现了一些问题,希望与大家分享。
问题引入
以下代码用于取得Person类中的全部构造方法:
package reflectDemo01; import java.lang.reflect.Constructor; //导入反射包 class Person{ private String name; private int age; public Person(String name) { //第一个构造方法 this.setName(name); } public Person(String name,int age) { //第二个构造方法 this.setName(name); this.setAge(age); } public void setName(String name) { this.name=name; } public void setAge(int age) { this.age=age; } public String toString() { //覆写toString()方法 return "姓名:"+this.name+" 年龄:"+this.age; } } public class ReflectDemo01 { public static void main(String args[]) { Class<?>c=null; //声明Class对象 try { c=Class.forName("reflectDemo01.Person"); //实例化Class对象 } catch (ClassNotFoundException e) { e.printStackTrace(); //处理异常 } Constructor<?> cons[]=c.getConstructors(); //取得全部公共构造方法 for(int i=0;i<cons.length;i++) { System.out.println(cons[i]); //循环输出 } } }
运行结果如下:
通过运行结果可以看到返回的对象数组中构造方法的顺序是定义的顺序
这时将定义的两个构造方法位置交换:
public Person(String name,int age) { //原第二个构造方法 this.setName(name); this.setAge(age); } public Person(String name) { //原第一个构造方法 this.setName(name); }
得到如下结果:
输出结果也交换了顺序,与定义的顺序一致。
那我们是否能得出通过getConstructors()方法获取的构造方法顺序与定义顺序一致的结论呢?
下面我们将一个无参构造方法加入代码:
public Person(){} //新加入的无参构造 public Person(String name,int age) { //原第二个构造方法 this.setName(name); this.setAge(age); } public Person(String name) { //原第一个构造方法 this.setName(name); }
运行结果如下:
可见此时的方法输出顺序是逆序,并不是定义的顺序,再调换一下顺序:
public Person(String name) { //第一个构造方法 this.setName(name); } public Person(String name,int age) { //第二个构造方法 this.setName(name); this.setAge(age); } public Person(){} //新加入的无参构造
再次调换顺序后的运行结果:
输出的结果仍是逆序,那么为什么是这样呢?
问题分析
public Constructor<?>[] getConstructors() throws SecurityException
查看API文档后发现getConstructors()方法返回的是此类公共构造方法的 Constructor 对象数组 ,并没有对数组存储顺序的描述,于是我猜测此方法用了栈(Stack)的存储方式,最后用先进后出(FILO)的方式输出。
为了验证猜测,我向Person类中添加了一个浮点型(Float)的属性score,并增加了一个构造方法。
private String name; private int age; private float score; public Person(){} //第一个无参构造 public Person(String name) { //第二个构造方法 this.setName(name); } public Person(String name,int age) { //第三个构造方法 this.setName(name); this.setAge(age); } public Person(float score) {} //新增的第四个构造方法
运行结果:
此时无论怎么调换方法顺序,仍是逆序输出,但再次加入2个构造方法之后,顺序发生了变化:
public Person(){} // 第一个无参构造 public Person(String name) { //第二个构造方法 this.setName(name); } public Person(String name,int age) { //第三个构造方法 this.setName(name); this.setAge(age); } public Person(float score) {} //第四个构造方法 public Person(String name,float score) {} //新增的第五个构造方法 public Person(String name,int age,float score) {} //新增的第六个构造方法
运行结果:
从运行结果可以看见输出顺序发生了变化,虽然有一定规律但并不是有序的,同时也证明了我的猜测是错误的。
问题结论
进一步查看API文档发现在getDeclaredConstructors()方法的描述中有这样一句话:
The elements in the array returned are not sorted and are not in any particular order.
也就是说返回数组中的元素没有排序,也没有任何特定的顺序,这样的描述同时存在于getDeclaredFields()方法和getDeclaredMethods()中。我又向Person类中加入了若干构造方法,发现分别在第3,6,13,15,27次时,输出顺序全部发生改变。由此可以得出结论:
在取得全部构造方法,普通方法和属性的时候,返回数组里元素的位置是完全随机的。
所以不要采用getConstructors()方法,用数组下标获取构造方法的方式初始化对象,以免以后在类中新增构造方法时出现异常。
可以采用较为安全的getConstrutor()方法指定参数类型,再通过newInstance()方法为对象初始化:
Constructor<?> con1=c.getConstructor(String.class,int.class); //指定参数类型 Person per=(Person)con1.newInstance("MaYuKang",20); //传入参数 System.out.println(per);
运行结果:
以上所有代码及运行结果均使用Eclipse编译器,JDK10.0.1版本,如有描述不当,望大家多多纠正与补充。
- Java基础39-通过反射机制获取类的方法、属性和构造方法
- java中的反射机制,以及如何通过反射获取一个类的构造方法 ,成员变量,方法,详细。。
- java 反射机制(通过getGenericSuperclass()方法获取到父类泛型的类型)
- java中反射机制通过字节码文件对象获取字段和函数的方法
- java通过反射获取私有的构造方法,及反射擦除泛型数据类型约束
- Android(java)学习笔记108:通过反射获取私有构造方法并且使用
- java中反射机制通过字节码文件对象获取字段和函数的方法
- 有关java通过反射机制调用类中自有方法的问题
- 关于Java new对象构造方法执行顺序 解释恶汉单例模式死循环问题
- 关于反射中.getDeclaredContructor()返回构造方法顺序的问题
- JAVA 采用反射机制 获取构造方法
- java中通过反射获取方法并且调用(getMethod和invoke深入)实践
- java中通过反射获取方法并且调用(getMethod和invoke深入)实践
- Java 通过反射机制动态调用java类方法
- java 通过反射获取调用类方法及属性
- java静态代码块 构造代码块 构造方法的执行顺序及注意问题
- 使用反射创建Bean、Spring中是如何根据类名配置创建Bean实例、Java提供了Class类获取类别的字段和方法,包括构造方法
- Android(java)学习笔记107-0:通过反射获得构造方法并且使用
- Java反射之通过反射获取一个对象的方法信息
- java通过反射获取调用变量以及方法