基於《Java編程思想》第四版html
咱們要操做一個類實例對象時,通常都要先知道這個類有哪些方法或者成員變量。反射就是在咱們不知道這個類有哪些方法或成員變量時,使用特定方式獲得類的這些信息,再根據特定規則去調用對應的方法操做類實例對象。
這中間有兩個未知條件java
類信息是經過Class
記錄的,規則是由程序員定的。程序員
Class
是一個記錄類信息的類,每一個類(包括Class
)都會有一個Class
對象。其實現也很好猜想和理解:編譯器掃描完代碼,就能知道類的具體信息,好比有哪些方法,而後把這些信息保存到Class
對象中。
由於Class
對象並非程序員本身實例化的,因此必須得有一個肯定的名字,約定就叫作class
。咱們能夠經過訪問class
對象獲得類的信息。
爲了獲取class
對象,有三種方法編程
類名.class
直接訪問Class c = Integer.class;
Class.forName(類名)
函數獲取(可能拋出異常,須要放在try catch
中)Class c = Class.forName("Integer");
對象.class
獲取Integer n = new Integer (); Class c = n.getClass();
不論經過哪一種方式獲取的class
對象都是同一個對象,也就是說每一個類全局只有一個class
對象。能夠查看文檔知道Class
有哪些接口,之後多用用就會熟能生巧了。api
當咱們使用反射時,除了Class
對象記錄的信息外,還須要一個規則來約束實現者和使用者。
假定有一個持久化功能的規則以下oracle
表名.列名=值
的方式按照這個規則實現一個使用了反射的持久化函數,裏面沒有具體的類型框架
// 略去了異常處理的代碼 public static void save( String s ) { String[] tmp = s.split("\\."); String table = tmp[0]; String column = tmp[1].split("=")[0]; String value = tmp[1].split("=")[1]; Class c = Class.forName(table); Method m = c.getMethod("set" + column, String.class); Object o = c.getConstructor().newInstance(); m.invoke(o,value); }
按規則要求實現兩個持久化類函數
class Book{ private String name; public Book(){ } public void setName(String name){ this.name = name; System.out.println("Book name = " + name); } } class Person{ private String name; public Person(){ } public void setName(String name){ this.name = name; System.out.println("Person name = " + name); } }
使用者無需關注具體類型,就能夠完成存儲功能this
public static void main(String[] args) { save("Person.Name=Jack"); save("Book.Name=Five"); }
後續有新增的持久化類時,只要按照規則實現,也能直接嵌入到這個框架中了。code
有不少框架都使用了反射機制,後面還要繼續深刻去了解反射的使用方式。