關(guān)于Java反射機制中通過getConstructors方法獲取類中全部構(gòu)造方法順序的問題
近日學(xué)習(xí)java反射機制的過程中了解到的getConstructors()方法,此方法用于取得全部構(gòu)造方法,在測試過程發(fā)現(xiàn)了一些問題往衷,希望與大家分享。
問題引入
以下代碼用于取得Person類中的全部構(gòu)造方法:
package reflectDemo01;
import java.lang.reflect.Constructor; //導(dǎo)入反射包
class Person{
private String name;
private int age;
public Person(String name) { //第一個構(gòu)造方法
this.setName(name);
}
public Person(String name,int age) { //第二個構(gòu)造方法
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(); //取得全部公共構(gòu)造方法
for(int i=0;i<cons.length;i++) {
System.out.println(cons[i]); //循環(huán)輸出
}
}
}
運行結(jié)果如下:
通過運行結(jié)果可以看到返回的對象數(shù)組中構(gòu)造方法的順序是定義的順序
這時將定義的兩個構(gòu)造方法位置交換:
public Person(String name,int age) { //原第二個構(gòu)造方法
this.setName(name);
this.setAge(age);
}
public Person(String name) { //原第一個構(gòu)造方法
this.setName(name);
}
得到如下結(jié)果:
輸出結(jié)果也交換了順序黑忱,與定義的順序一致。那我們是否能得出通過getConstructors()方法獲取的構(gòu)造方法順序與定義順序一致的結(jié)論呢勒魔?
此時將一個無參構(gòu)造方法加入代碼甫煞,:
public Person(){} //新加入的無參構(gòu)造
public Person(String name,int age) { //原第二個構(gòu)造方法
this.setName(name);
this.setAge(age);
}
public Person(String name) { //原第一個構(gòu)造方法
this.setName(name);
}
運行結(jié)果如下:
運行結(jié)果可見輸出順序是逆序,并不是定義的順序冠绢,再調(diào)換一下順序:
public Person(String name) { //第一個構(gòu)造方法
this.setName(name);
}
public Person(String name,int age) { //第二個構(gòu)造方法
this.setName(name);
this.setAge(age);
}
public Person(){} //新加入的無參構(gòu)造
再次調(diào)換順序后的運行結(jié)果:
輸出的結(jié)果仍是逆序危虱,那到底getConstructors()方法返回結(jié)果的順序如何?
問題引入
public Constructor<?>[] getConstructors() throws SecurityException
查看API文檔后發(fā)現(xiàn)getConstructors()方法返回的是此類公共構(gòu)造方法的 Constructor 對象數(shù)組 ,并沒有對數(shù)組存儲順序的描述唐全,于是我猜測此方法用了棧(Stack)的存儲方式埃跷,最后用先進后出(FILO)的方式輸出蕊玷。
為了驗證猜測,我向Person類中添加了一個浮點型(Float)的屬性score,并增加了一個構(gòu)造方法弥雹。
private String name;
private int age;
private float score;
public Person(){} //第一個無參構(gòu)造
public Person(String name) { //第二個構(gòu)造方法
this.setName(name);
}
public Person(String name,int age) { //第三個構(gòu)造方法
this.setName(name);
this.setAge(age);
}
public Person(float score) {} //新增的第四個構(gòu)造方法
運行結(jié)果:
此時無論怎么調(diào)換方法順序垃帅,仍是逆序輸出,但再次加入2個構(gòu)造方法之后剪勿,順序發(fā)生了變化:
public Person(){} // 第一個無參構(gòu)造
public Person(String name) { //第二個構(gòu)造方法
this.setName(name);
}
public Person(String name,int age) { //第三個構(gòu)造方法
this.setName(name);
this.setAge(age);
}
public Person(float score) {} //第四個構(gòu)造方法
public Person(String name,float score) {} //新增的第五個構(gòu)造方法
public Person(String name,int age,float score) {} //新增的第六個構(gòu)造方法
運行結(jié)果:
從運行結(jié)果可以看見輸出順序發(fā)生了變化贸诚,雖然有一定規(guī)律但并不是有序的,由此便可以得出結(jié)論厕吉。
問題結(jié)論
進一步查看API文檔發(fā)現(xiàn)在getDeclaredConstructors()方法的描述中有這樣一句話:
The elements in the array returned are not sorted and are not in any particular order.
也就是說返回數(shù)組中的元素沒有排序酱固,也沒有任何特定的順序,這樣的描述同時存在于getDeclaredFields()方法和getDeclaredMethods()中头朱。我又向Person類中加入了若干構(gòu)造方法运悲,發(fā)現(xiàn)分別在第3,6,13,15,27次時,輸出順序全部發(fā)生改變项钮。由此可以得出結(jié)論:
① 在取得全部構(gòu)造方法班眯,普通方法和屬性的時候,返回數(shù)組里元素的位置是完全隨機的烁巫。
② 這種隨機指的不是每次執(zhí)行返回的結(jié)果不同署隘,而是隨著方法和屬性的增加而改變返回順序。
所以不要采用getConstructors()方法亚隙,用數(shù)組下標獲取構(gòu)造方法的方式初始化對象磁餐,以免以后在類中新增構(gòu)造方法時出現(xiàn)異常。
可以采用較為安全的getConstrutor()方法指定參數(shù)類型阿弃,再通過newInstance()方法為對象初始化:
Constructor<?> con1=c.getConstructor(String.class,int.class); //指定參數(shù)類型
Person per=(Person)con1.newInstance("MaYuKang",20); //傳入?yún)?shù)
System.out.println(per);
運行結(jié)果:
以上所有代碼及運行結(jié)果均使用Eclipse編譯器崖媚,JDK10.0.1版本。如有描述不當恤浪,望大家多多糾正與補充,覺得有用就點個贊唄肴楷。