Java反射機制demo(三)—獲取類中的構造函數
1,獲取類中所有的構造函數
如下面的代碼中所示,這個類中顯式的構造函數有五個。
空構造:
- public UserInfo()
帶參構造有四個:
- public UserInfo(int userId)
- private UserInfo(String name)
- protected UserInfo(int userId, String name)
- public UserInfo(int userId, String name, int age)
注意 他們的訪問修飾符。
1 package com.aaron.reflect; 2 3 public class UserInfo{ 4 private int userId; 5 private String name; 6 private int age; 7 8 public UserInfo(){} 9 10 public UserInfo(int userId){ 11 this.userId = userId; 12 } 13 private UserInfo(String name){ 14 this.name = name; 15 } 16 17 public UserInfo(int userId, String name, int age) { 18 super(); 19 this.userId = userId; 20 this.name = name; 21 this.age = age; 22 } 23 24 public int getUserId() { 25 return userId; 26 } 27 public void setUserId(int userId) { 28 this.userId = userId; 29 } 30 public String getName() { 31 return name; 32 } 33 public void setName(String name) { 34 this.name = name; 35 } 36 public int getAge() { 37 return age; 38 } 39 public void setAge(int age) { 40 this.age = age; 41 } 42 @Override 43 public String toString() { 44 return "UserInfo [userId=" + userId + ", name=" + name + ", age=" + age + "]"; 45 } 46 47 }
我們可以使用Class類中的Constuctor<?>[] getConstructors()方法,來獲得這個類的構造函數。
JDK API文檔里,對這個方法的描述如下:
返回一個包含某些 Constructor 對象的數組,這些對象反映此 Class 對象所表示的類的所有公共構造方法。如果該類沒有公共構造方法,或者該類是一個數組類,或者該類反映一個基本類型或 void,則返回一個長度為 0 的數組。 注意,此方法返回 Constructor<T> 對象的數組(即取自此類構造方法的數組)時,此方法的返回類型是 Constructor<?>[],不是 預期的 Constructor<T>[]。此少量信息的返回類型是必需的,因為從此方法返回之后,該數組可能被修改以保存不同類的 Constructor 對象,而這將違反 Constructor<T>[] 的類型保證。
總之,返回了表示此類公共構造方法的Constructor對象數組。注意,這里是公共構造方法。
測試類的代碼如下:
Constuctor<?>[] getConstructors()
package com.aaron.reflect;
import java.lang.reflect.Constructor;
public class Demo2 {
public static void main(String[] args) {
Class<?> c = UserInfo.class;//獲取Class對象
Constructor<?> cons[] = c.getConstructors();//獲取構造函數的數組
//打印
for (Constructor<?> constructor : cons) {
System.out.println(constructor);
}
}
}
運行結果如下:
public com.aaron.reflect.UserInfo() public com.aaron.reflect.UserInfo(int,java.lang.String,int) public com.aaron.reflect.UserInfo(int)
運行的結果打印出了所有顯式聲明的,而且是公共的構造函數。
但是,這個順序和我們類里的定義順序是不一樣的,因此,從這個方法精准地定位一個構造函數是不可取的。真的亂序的嗎?API里沒有提到。但是,另外一個方法的文檔中提到了。這個方法是
Constuctor<?>[] getDeclaredConstructors()
這個方法返回Constructor對象的一個數組,這些對象包含了Class對象所表示的類中的所有構造方法。它們分別是公共,保護,默認(包),和私有構造。
返回數組中的元素沒有排序,也沒有任何特定的順序。
如果該類存在一個默認構造方法,則它包含在返回的數組中。如果此Class對象表示一個接口,一個基本類型,一個數組類或者void,則這個方法返回一個長度為0的數組。
測試類:
package com.aaron.reflect;
import java.lang.reflect.Constructor;
public class Demo2 {
public static void main(String[] args) {
Class<?> c = UserInfo.class;//獲取Class對象
Constructor<?> cons[] = c.getDeclaredConstructors();
//打印
for (Constructor<?> constructor : cons) {
System.out.println(constructor);
}
}
}
運行結果:
public com.aaron.reflect.UserInfo() public com.aaron.reflect.UserInfo(int,java.lang.String,int) public com.aaron.reflect.UserInfo(int) private com.aaron.reflect.UserInfo(java.lang.String) protected com.aaron.reflect.UserInfo(int,java.lang.String)
2,調用構造方法生成實例
Constructor<T> getConstructor(Class<?>... parameterTypes)
package com.aaron.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Demo2 {
public static void main(String[] args) {
Class<?> c = UserInfo.class;//獲取Class對象
try {
Constructor<?> constructor = c.getConstructor(int.class);//只有使用類字面常量才能夠獲取基本類型的Class對象
UserInfo userInfo = (UserInfo) constructor.newInstance(1);//構造實例
System.out.println(userInfo);
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意其中的注釋,只有使用類字面常量才能獲得int這種基本類型的Class對象。
而Integer.class和int.class所表示的Class必然不同,因為一個是泛型一個是基本類型。Integer繼承了java.lang.Number,而Number繼承了java.lang.Object。
下面給出運行結果。
UserInfo [userId=1, name=null, age=0]
