通過反射來獲取某一個類的構(gòu)造器:
1>獲取該類的字節(jié)碼對象审姓;
2>從該字節(jié)碼對象中去找需要獲取的構(gòu)造器;
Class類獲取構(gòu)造器方法:
Constructor類:
--表示類中構(gòu)造器的類型相满,Constructor的實例就是某一個類中的某一個構(gòu)造器;
public Constructor<?>[] getConstructors() ;
--該方法只能獲取當前Class所表示類的public修飾的構(gòu)造器劲腿;
public Constructor<?>[] getDeclaredConstructors();
--獲取當前Class所表示類的所有構(gòu)造器蔫劣,和訪問權(quán)限無關(guān)奕污;
public Constructor<T> getConstructor(Class<?>... parameterTypes);
--獲取當前Class所表示類中指定的一個public的構(gòu)造器
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);
--獲取當前Class所表示類中指定的一個構(gòu)造器巷懈;
參數(shù):parameterTypes
--表示:構(gòu)造器參數(shù)的Class類型;
public class _0_GetConstructor {
public static void main(String[] args) throws Exception{
// 獲取所有的構(gòu)造器
getAlls();
// 獲取指定的一個構(gòu)造器
getAppoint();
}
private static void getAlls() {
// 1.獲取構(gòu)造器所在類的字節(jié)碼對象
Class clz = User.class;
// 2.獲取clz對象中所有的構(gòu)造器
// 該方法只能獲取當前Class所表示類的public修飾的構(gòu)造器癌蓖;
Constructor<User>[] cons = clz.getConstructors();
System.out.println(cons.length);//2
for (Constructor c : cons) {
System.out.println(c);
//public com.reflection._1_constructor.User()
//public com.reflection._1_constructor.User(java.lang.String)
}
System.out.println("------------------------------");
// 獲取當前Class所表示類的所有構(gòu)造器,和訪問權(quán)限無關(guān);
cons = clz.getDeclaredConstructors();
System.out.println(cons.length);//3
for (Constructor c : cons) {
System.out.println(c);
//public com.reflection._1_constructor.User()
//public com.reflection._1_constructor.User(java.lang.String)
//private com.reflection._1_constructor.User(java.lang.String,int)
}
}
public static void getAppoint() throws Exception {
System.out.println("------------------------------");
// 1.獲取構(gòu)造器所在類的字節(jié)碼對象
Class clz = User.class;
// 需求1:獲取public User()
Constructor<User> con = clz.getConstructor();
System.out.println(con);//public com.reflection._1_constructor.User()
// 需求2:獲取public User(String name)
con = clz.getConstructor(String.class);
System.out.println(con);
// 需求3:獲取public User(String name ,int age)
// con = clz.getConstructor(String.class,int.class);//報錯:Exception in thread "main" java.lang.NoSuchMethodException:
// com.reflection._1_constructor.User.<init>(java.lang.String, int)
con = clz.getDeclaredConstructor(String.class,int.class);
System.out.println(con);
}
}
class User{
public User(){}
public User(String name){}
private User(String name ,int age){}
}
構(gòu)造器最大的作用:創(chuàng)建對象;
為什么使用反射創(chuàng)建對象而不直接使用new呢舷蟀?
在框架中,提供給我們的都是字符串其徙;
很多框架(比如Spring)都是配置化的(比如通過XML文件配置JavaBean,Action之類的)河哑,為了保證框架的通用性,它們可能需要根據(jù)配置文件加載不同的對象或類羡滑,調(diào)用不同的方法,這個時候就必須用到反射——運行時動態(tài)加載需要加載的對象泥耀。
使用反射創(chuàng)建對象
步驟:
1.找到構(gòu)造器所在類的字節(jié)碼對象蜘醋;
2.獲取構(gòu)造器對象;
3.使用反射粥航,創(chuàng)建對象杨凑;
Constructor<T>類:表示類中構(gòu)造器的類型,Constructor的實例就是某一個類中的某一個構(gòu)造器驹吮;
常用方法:
public T newInstance(Object... initarges);
-若調(diào)用帶參數(shù)的構(gòu)造器脆淹,只能使用該方式;
-參數(shù):initarges,表示調(diào)動構(gòu)造器的實際參數(shù)盗棵;
-返回:返回創(chuàng)建的實例泰涂,T表示Class所表示類的類 型僵井;
如果:一個類中的構(gòu)造器是外界可以 直接訪問的,同時沒有參數(shù)社搅,那么可以直接使用Class類中的newInstance()方法創(chuàng)建對象淌实;
-public Object newInstance();//相當于new 類名();
訪問私有的成員
-(Constructor、Method、Field):
必須先設(shè)置可訪問的:
語法:對象.setAccessible(true);
見源碼:
-public final class Constructor<T> extends Executable ...
-public abstract class Executable extends AccessibleObject{
public static void setAccessible(AccessibleObject[] array,
boolean flag)
}
//使用反射調(diào)用構(gòu)造器所在類來創(chuàng)建其對象
public class _1_CreateObject {
public static void main(String[] args) throws Exception{
Class<Person> clz = Person.class;
Person p = clz.newInstance();
Constructor<Person> con = clz.getConstructor();
Person instance = con.newInstance();//調(diào)用無參數(shù)構(gòu)造器
con = clz.getConstructor(String.class);
con.newInstance("INSOMNIA");
con = clz.getDeclaredConstructor(String.class,int.class);
// con.newInstance("INSOMNIA",18);//報錯留美,原因:
//Exception in thread "main" java.lang.IllegalAccessException://非法訪問異常
//Class com.reflection._1_constructor._1_CreateObject
//can not access a member of class com.reflection._1_constructor.Person with modifiers "private"
/** 設(shè)置當前構(gòu)造器可以訪問*/
con.setAccessible(true);//可解決上述問題;使用枚舉谎砾,即使反射也不行逢倍;
con.newInstance("INSOMNIA",18);
}
}
class Person{
public Person(){
System.out.println("調(diào)用無參數(shù)構(gòu)造器");
}
public Person(String name){
System.out.println("調(diào)用有參數(shù)構(gòu)造器"+name);
}
private Person(String name ,int age){
System.out.println("調(diào)用有參數(shù)構(gòu)造器"+"name = "+name+" & "+"age = "+age);
}
}