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”。