>反射要注意的點:
- 反射入口,怎麼獲取類、方法、屬性對象
- 其中方法中特殊的:通過反射的構造來獲取對象
- 其中屬性中的應用:通過反射的屬性對象 獲取屬性名 拼接get/set方法名 進一步調用方法的應用
>獲取入口點Class<?> 的方式:
- Class.forNme()
- 類名.class
- 對象引用.getClass()
>Reflection初步,以及解析一個類的信息
public class Re {
/**
* 反射?(自己分析自己:通過自己的語法分析自己的類結構,並且能夠動態執行自己的類)
* 通過反射可以分析一個類的信息/結構
* 可以執行一個類的方法 有些類沒有辦法new 比如在遠端,不在當前的class path下
*
* spring ioc(工廠方法模式) aop(代理模式/bytecode instrument:插樁,修改字節碼文件;一個重要的庫:cglib主要完成插樁功能)
* 1.編譯時環境:Java代碼和編譯成class文件的階段;運行時環境:jvm運行編譯後的class文件的階段;
* 源碼-->編譯-->字節碼-->運行
* 在Java的運行環境中,對於任意一個類,可以通過反射,知道這個類有哪些屬性和方法;對於任意一個對象可以通過反射調用它的任意一個方法;
* 反射機制(reflection):動態獲取類的信息,動態調用對象的方法
*
* 2.re主要功能:
* 在運行時判斷任意一個對象所屬的類
* 在運行時構造任意一個類的對象 (在編譯期,我們可以通過new寫在程序代碼裏)
* 在運行時判斷任意一個類所具有的成員變量和方法
* 在運行時調用任意一個對象的方法
*
* 3.re概念:
* Java動態語言性質(準動態語言):re機制允許程序在運行時透過Java提供的Reflection API取得任意一個 已知名稱 的類的內部信息
* 包括:其modifiers(如public static...)、superclass(如Object...)、實現之Interface(如Serializable)
* 也包括field成員變量和method方法的所有信息
* 並可以在運行時改變field的內容或者調用method方法
* 如:Spring中 bean的信息配置在 applicationContext.xml中,配置的類的名字都是字符串,Spring如何將字符串對應的類生成出來? 反射!
* 沒有反射,所有的框架都不存在。
*
* 4.動態語言概念:
* “程序運行時,允許改變程序結構或變量類型,這種語言稱爲動態語言” 如: var a="hello"; a=1;
* 從這個觀點看:Perl,Python,Ruby是動態語言 ;C++,Java,C#不是動態語言;
* 但是Java具有動態相關機制:Reflection。我們可以在 運行時 加載,探知,使用編譯期間完全未知的classes。
* 換句話說,Java程序可以加載一個運行時才得知名稱的class,獲悉完整的構造(不包括method定義:內部具體實現),並生成對象實體,或對其field設值,或喚起其method。
* 這種“看透class”的能力,稱爲introspection。
*
* 5.Re API
* JDK中,主要由以下類實現Java反射機制:
* (主要位於java.lang.reflect包中)
* --Class類:代表一個類
* --Field類:代表類的成員變量
* --Method類:代表類的方法
* --Constructor類:代表類的構造方法
* --Array類:提供動態創建數組,以及訪問數組的元素的靜態方法
* @throws ClassNotFoundException
*
*/
//從命令行接收一個字符串(該字符串是某個類的全名)
//打印出該類中所有的所有的方法聲明
public static void main(String[] args) throws ClassNotFoundException {
//java.lang.Class java中每個對象都會有一個與之關聯的Class對象,Class對象是jdk啓動的時候就加載的,Class對象是唯一的;如生成了n個字符串對象,都會唯一的對應一個Class對象。
//Class類是反射的入口點,Re必須從Class開始
Class<?> classType=Class.forName(args[0]);//編譯時jdk並不知道這是什麼,運行時傳入
//對於類中定義的任意一個方法,都會有一個與之關聯的Method對象,可以獲得除了方法體之外的內容
Method[] methods = classType.getDeclaredMethods();
for(Method method : methods){
System.out.println(method);
}
}
}
>通過反射獲取一個類的實例和方法的調用
public class InvokeTester {
public int add(int para1, int para2) {
return para1 + para2;
}
public String echo(String msg) {
return "hello" + msg;
}
public static void main(String[] args) throws Exception {
//java內置的語法形式.class 會獲得InvokeTester類所對應的Class對象
Class<?> classType = InvokeTester.class;
//創建一個Class對象 所表示的類 的實例,newInstance使用條件:需要一個不帶參數的構造方法
Object invokeTester = classType.newInstance();
//以上兩行代碼等價於
InvokeTester it = new InvokeTester();
//獲取add()方法對應的Method對象(需要名字和參數;返回值並不屬於Java方法重載的範疇) ...可變參數/相當於一個數組
Method addMethod = classType.getMethod("add", new Class[]{int.class,int.class});
// 方法所在目標對象 參數
Object result = addMethod.invoke(invokeTester, new Object[]{1,2});
System.out.println((Integer)result);//3
//以上兩行代碼等價於
it.add(1, 2);
Method echoMethod = classType.getMethod("echo", new Class[]{String.class});
result = echoMethod.invoke(invokeTester, "java");
System.out.println((String)result);//hellojava
//以上兩行代碼等價於
it.echo("java");
}
}
>反射構造方式獲取一個類的實例、反射屬性進一步反射get/set方法
public class ReflectTester {
public Object copy(Object object) throws Exception {
Class<?> classType = object.getClass();
System.out.println(classType.getName());
// 通過構造方法生成類的實例 構造方法看參數區分
Constructor<?> constructor = classType.getConstructor(new Class[] {});
Object objectCopy = constructor.newInstance(new Object[] {});
// 上面兩行代碼等價於(僅能用於不帶參構造)
Object objectCopy2 = classType.newInstance();
// 獲得對象所有的屬性
Field[] fields = classType.getDeclaredFields();
for (int i = 0; i < fields.length; ++i) {
Field field = fields[i];
String fieldName = field.getName();
// 獲得屬性的首字母並轉換爲大寫 區間一般爲左閉右開
String firstLetter = fieldName.substring(0, 1).toUpperCase();
// 獲得屬性對應的getXXX() 名字
String getMethodName = "get" + firstLetter + fieldName.substring(1);
// 獲得屬性對應的setXXX() 名字
String setMethodName = "set" + firstLetter + fieldName.substring(1);
// 獲取get方法對應的method對象
Method getMethod = classType.getMethod(getMethodName, new Class[] {});
// 獲取set方法對應的method對象
Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() });
Object value = getMethod.invoke(object, new Object[] {});
System.out.println(fieldName + ":" + value);
setMethod.invoke(objectCopy, new Object[] { value });
}
return objectCopy;
}
public static void main(String[] args) throws Exception {
Customer customer = new Customer();
customer.setId(new Long(1));
customer.setName("zhangsan");
customer.setAge(18);
Customer customerCopy = (Customer) new ReflectTester().copy(customer);
System.out.println(customerCopy.getId() + "," + customerCopy.getName() + "," + customerCopy.getAge());
}
}
class Customer {
private Long id;
private String name;
private int age;
public Customer() {
// TODO Auto-generated constructor stub
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}