1.什麼是反射( reflect)
JAVA反射機制是運行狀態中,對於任意一個類都能夠知道這個類的所有屬性個方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取信息及動態調用對象的方法的功能稱爲java語言的反射機制。
簡單說:在運行狀態下,通過class文件對象,去使用構造方法,成員變量和成員方法
注意:在反射中包含Declared的方法表示獲取私有的成員內容,一般結合setAccessible(true)方法一起使用
2.創建Class文件的三種方式
Class.forName("類全名");
對象名.getClass();
類名.class
推薦使用:Class.forName("類全名");
3.獲取構造方法並創建對象
概述:
java.lang.reflect.Constructor:構造方法管理器,通過該對象的newInstance方法能有創建構造方法
步驟
1、獲取Class對象2、通過調用getDeclaredConstructor或者getConstructor 方法創建構造器(Constructor)對象,如果構造方法沒有形式參數寫nullpublic Constructor getDeclaredConstructor(形式參數1對應的.class對象, 形式參數2對應的.class對象....):該方法可以獲取私有構造方法public Constructor getConstructor(形式參數1對應的.class對象, 形式參數2對應的.class對象....):該方法不能獲取私有構造方法3、如果獲取到的是私有的構造方法的構造器對象,需要調用構造器對象的setAccessible(true)方法4、通過構造器對象的newInstance(實際參數1, 實際參數2)創建對象,如果沒有實際參數寫null
舉例
1、通過private Person(String name, int age)創建對象
Class clazz = Class.forName("com.itcast.Person"); //必須通過類全名獲取
Constructor con = clazz.get DeclaredConstructor(String.class, int.class);//形式參數列表對應的.class列表
con.setAccessible(true);//此處不設置,無法創建該對象,因爲構造方法是私有的Object obj = con.newInstance("zhangsan",120); //調用newInstance(實際參數列表)創建對象
2、通過public Person()創建對象
Class clazz = Class.forName("com.itcast.Person");//必須通過類全名獲取
Constructor con = clazz.getDeclaredConstructor(null); //因爲沒有形式參數,所以寫null
con.setAccessible(true);//此處不設置,無法創建該對象,因爲構造方法是私有的
Object obj = con.newInstance(); //因爲不需要實際參數,所以調用無參的newInstance方法4.獲取屬性並調用
概述:
java.lang.reflect.Field:屬性管理器對象,可以對該類的對象的屬性值進行修改和獲取
1、獲取Class對象
2、通過調用getDeclaredField("屬性名")或通過調用getField("屬性名") 獲取屬性管理器
3、如果獲取的是私有的屬性,調用屬性管理器的 setAccessible(true)方法
4、調用屬性管理器的set(該類的對象,值) 來設置屬性值
調用屬性管理器的get(該類的對象)來獲取屬性值
舉例
Person p1 = new Person();
Person p2= new Person(); Class clazz = Class.forName("Person"); //第一步獲取Class對象
Field field = clazz.getDeclaredField("name");
//第二步通過調用getDeclaredField("屬性名")或通過調用getField("屬性名") 獲取屬性管理器
field.setAccessible(true); //第三步如果獲取的是私有的屬性,調用屬性管理器的setAccessible(true)方法
field.set(p1, "張三"); //第四步用屬性管理器的set(該類的對象,值) 來設置屬性值
field.setAccessible(true); //第三步如果獲取的是私有的屬性,調用屬性管理器的setAccessible(true)方法
field.set(p1, "張三"); //第四步用屬性管理器的set(該類的對象,值) 來設置屬性值
field.set(p2, "李四");
System.out.println(field.get(p1)); //第四步調用屬性管理器的get(該類的對象)來獲取屬性值
System.out.println(field.get(p2));
System.out.println(field.get(p1)); //第四步調用屬性管理器的get(該類的對象)來獲取屬性值
System.out.println(field.get(p2));
5.獲取成員方法並調用
概述:
java.lang.reflect.Method:方法管理器,可以執行該類的對象的方法
步驟
1、獲取Class對象
2、通過調用getDeclaredMethod("方法名",形式參數1.class, 形式參數2.class..)或通過調用geMethod("方法名",形式參數1.class, 形式參數2.class..) 獲取屬性管理器,如果沒有形式參數寫null
3、如果獲取的是私有的方法,調用方法管理器的 setAccessible(true)方法
4、通過屬性管理器的invoke(該類的對象,實際參數)來執行方法,如果沒有實際參數寫null
案例
Person p1 = new Person("張三",13);
Person p2= new Person("李四",14);
Class clazz = Class.forName("Person");
/*
* 調用setName方法
*/
Method setName = clazz.getDeclaredMethod("setName", String.class);
setName.setAccessible(true); //如果getName方法是私有的,此處必須寫
setName.invoke(p1, "張三改");
/*
* 調用getName方法
*/
Method getName = clazz.getDeclaredMethod("getName", null); //獲取Person類的getName方法對應的方法管
getName.setAccessible(true); //如果getName方法是私有的,此處必須寫
Object object = getName.invoke(p1, null); //執行p1對象的getName方法,並且將返回值賦值給object
System.out.println(object);
Person p2= new Person("李四",14);
Class clazz = Class.forName("Person");
/*
* 調用setName方法
*/
Method setName = clazz.getDeclaredMethod("setName", String.class);
setName.setAccessible(true); //如果getName方法是私有的,此處必須寫
setName.invoke(p1, "張三改");
/*
* 調用getName方法
*/
Method getName = clazz.getDeclaredMethod("getName", null); //獲取Person類的getName方法對應的方法管
getName.setAccessible(true); //如果getName方法是私有的,此處必須寫
Object object = getName.invoke(p1, null); //執行p1對象的getName方法,並且將返回值賦值給object
System.out.println(object);
6.反射練習
1:通過反射修改成員變量的值,包括私有
2: 通過反射運行配置文件
在JAVA項目下新建配置文件config,內容爲: class=Person
name=jack
JAVA代碼:
Properties p = new Properties();
p.load(new FileReader("config"));
String className = (String)p.get("class");
String name = (String)p.get("name");
Class clazz = Class.forName(className);
//創建對象
Constructor constructor = clazz.getConstructor(null);
Object instance = constructor.newInstance();
//通過setName設置name屬性
Method setName = clazz.getDeclaredMethod("setName", String.class);
setName.invoke(instance,name );
//通過getName設置name屬性
Method method = clazz.getDeclaredMethod("getName",null);
Object object = method.invoke(instance, null);
System.out.println(object);
p.load(new FileReader("config"));
String className = (String)p.get("class");
String name = (String)p.get("name");
Class clazz = Class.forName(className);
//創建對象
Constructor constructor = clazz.getConstructor(null);
Object instance = constructor.newInstance();
//通過setName設置name屬性
Method setName = clazz.getDeclaredMethod("setName", String.class);
setName.invoke(instance,name );
//通過getName設置name屬性
Method method = clazz.getDeclaredMethod("getName",null);
Object object = method.invoke(instance, null);
System.out.println(object);
3: 通過反射給 ArrayList<Integer>中添加String 類型的數據
ArrayList list = new ArrayList();
list.add(123);
Class clazz = Class.forName("java.util.ArrayList");//必須通過類全名獲取
Method method = clazz.getDeclaredMethod("add", Object.class);
method.setAccessible(true);
method.invoke(list, "ss");
for(Object obj: list){
System.out.println(obj);
}
list.add(123);
Class clazz = Class.forName("java.util.ArrayList");//必須通過類全名獲取
Method method = clazz.getDeclaredMethod("add", Object.class);
method.setAccessible(true);
method.invoke(list, "ss");
for(Object obj: list){
System.out.println(obj);
}