基本概念:什麼是 Java 的反射機制
1、JAVA反射機制是在執行狀態中,
對於任意一個類,都能夠知道這個類的所有屬性和方法;
對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;
這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。
2、Java反射機制主要提供了以下功能:
在執行時判斷任意一個物件所屬的類;
在執行時構造任意一個類的物件;
在執行時判斷任意一個類所具有的成員變數和方法;
在執行時呼叫任意一個物件的方法;
生成動態代理。
3、反射技術大量用於Java設計模式和框架技術,最常見的設計模式就是工廠模式和單例模式。
單例模式(Singleton)
這個模式主要作用是保證在Java應用程式中,一個類Class只有一個例項存在。在很多操作中,比如建立目錄 資料庫連線都需要這樣的單執行緒操作。這樣做就是為了節省記憶體空間,保證我們所訪問到的都是同一個物件。
單例模式要求保證唯一,那麼怎麼樣才能保證唯一性呢?對了,這就是靜態變數。單例模式有以下兩種形式:
第一種形式:
package reflect;
public class Singleton {
private Singleton() {
}
private static Singleton instance = new Singleton();
// 這裡提供了一個供外部訪問本class的靜態方法,可以直接訪問
public static Singleton getInstance() {
return instance;
}
}
class SingRun{
public static void main(String[] args){
//這樣的呼叫不被允許,因為構造方法是私有的。
//Singleton x=new Singleton();
//得到一個Singleton類例項
Singleton x=Singleton.getInstance();
//得到另一個Singleton類例項
Singleton y=Singleton.getInstance();
//比較x和y的地址,結果為true。說明兩次獲得的是同一個物件
System. out.println(x==y);
}
}
第二種形式:
public class Singleton {
//先申明該類靜態物件
private static Singleton instance = null;
//建立一個靜態訪問器,獲得該類例項。加上同步,表示防止兩個執行緒同時進行物件的建立
public static synchronized Singleton getInstance() {
//如果為空,則生成一個該類例項
if (instance == null){
instance = new Singleton();
}
return instance;
}
}
工廠模式(Factory)
工廠模式是我們最常用的模式了,著名的Jive論壇 ,就大量使用了工廠模式,工廠模式在Java程式系統可以說是隨處可見。
為什麼工廠模式是如此常用?是因為工廠模式利用Java反射機制和Java多型的特性可以讓我們的程式更加具有靈活性。用工廠模式進行大型專案的開發,可以很好的進行專案並行開發。就是一個程式設計師和另一個程式設計師可以同時去書寫程式碼,而不是一個程式設計師等到另一個程式設計師寫完以後再去書寫程式碼。其中的粘合劑就是介面和配置檔案。之前說利用介面可以將呼叫和實現相分離。那麼這是怎麼樣去實現的呢?工廠模式可以為我們解答。
我們先來回顧一下軟體的生命週期,分析、設計、編碼、除錯與測試。其中分析就是指需求分析,就是知道這個軟體要做成什麼樣子,要實現什麼樣的功能。功能知道了,這時就要設計了。設計的時候要考慮到怎麼樣高效的實現這個專案,如果讓一個專案團隊並行開發。這時候,通常先設計介面,把介面給實現介面的程式設計師和呼叫介面的程式設計師,在編碼的時候,兩個程式設計師可以互不影響的實現相應的功能,最後通過配置檔案進行整合。
程式碼示例:
interface InterfaceTest{
public void getName();//定義獲得名字的方法
}
介面有了,那麼得到這個介面,進行實現編碼的程式設計師應該怎麼做呢?對了,實現這個介面,重寫其中定義的方法
介面實現方法:
class Test1 implements InterfaceTest{
public void getName() {
System.out.println("test1");
}
}
class Test2 implements InterfaceTest{
public void getName() {
System.out.println("test2");
}
}
大家可以發現,當介面定義好了以後,不但可以規範程式碼,而且可以讓程式設計師有條不紊的進行功能的實現。實現介面的程式設計師根本不用去管,這個類要被誰去呼叫。 那麼怎麼能獲得這些程式設計師定義的物件呢?在工廠模式裡,單獨定義一個工廠類來實現物件的生產,注意這裡返回的介面物件。
工廠類,生產介面物件:
class Factory{
//建立私有的靜態的Properties物件
private static Properties pro=new Properties();
//靜態程式碼塊
static{
try {
//載入配置檔案
pro.load(new FileInputStream("file.txt"));
} catch (Exception e) {
e.printStackTrace();
}
}
private static Factory factory=new Factory();
private Factory(){}
public static Factory getFactory(){
return factory;
}
public InterfaceTest getInterface(){
InterfaceTest interfaceTest=null;//定義介面物件
try {
//根據鍵,獲得值,這裡的值是類的全路徑
String classInfo=pro.getProperty("test");
//利用反射,生成Class物件
Class c=Class.forName(classInfo);
//獲得該Class物件的例項
Object obj=c.newInstance();
//將Object物件強轉為介面物件
interfaceTest=(InterfaceTest)obj;
} catch (Exception e) {
e.printStackTrace();
}
//返回介面物件
return interfaceTest;
}
}
配置檔案內容:
test=factory.Test2
通過這個類,大家可以發現,在呼叫的時候,得到的是個介面物件。而一個介面變數可以指向實現了這個介面的類物件。在利用反射的時候,我們並沒有直接把類的 全路徑寫出來,而是通過鍵獲得值。這樣的話,就有很大的靈活性,只要改變配置檔案裡的內容,就可以改變我們呼叫的介面實現類,而程式碼不需做任何改變。在調 用的時候,我們也是通過介面呼叫,甚至我們可以連這個介面實現類的名字都不知道。
呼叫方法:
public class FactoryTest {
public static void main(String[] args) {
//獲得工廠類的例項
Factory factory=Factory.getFactory();
//呼叫獲得介面物件的方法,獲得介面物件
InterfaceTest inter=factory.getInterface();
//呼叫介面定義的方法
inter.getName();
}
}
上面的程式碼就是呼叫方法。大家可以發現,在呼叫的時候,我們根本沒有管這個介面定義的方法要怎麼樣去實現它,我們只知道這個介面定義這個方法起什麼作用就行了。上面程式碼執行結果要根據配置檔案來定。如果配置檔案裡的內容是test=factory.Test2。那麼表示呼叫factory.Test2這個 類裡實現介面的方法,這時候列印“test2”。如果配置檔案裡的內容是test=factory.Test1。那麼表示呼叫factory.Test1 這個類裡實現介面的方法,這時候列印“test1”。