1. 程式人生 > 實用技巧 >PHP之專案環境變數設定

PHP之專案環境變數設定

反射

概述

反射庫(reflection library) 提供了一個非常豐富且精心設計的工具集, 以便編寫能夠動 態操縱 Java 程式碼的程式。這項功能被大量地應用於 JavaBeans 中, 它是 Java元件的體系結構 (有關 JavaBeans 的詳細內容在卷 II中闡述)。使用反射, Java 可以支援 Visual Basic 使用者習慣 使用的工具。特別是在設計或執行中新增新類時, 能夠快速地應用開發工具動態地查詢新添 加類的能力。 能夠分析類能力的程式稱為反射(reflective)。反射機制的功能極其強大,在下面可以看 到, 反射機制可以用來:

•在執行時分析類的能力。

•在執行時檢視物件, 例如, 編寫一個 toString方法供所有類使用。

•實現通用的陣列操作程式碼。

•利用 Method 物件, 這個物件很像中的函式指標。

Class類

在程式執行期間,Java執行時系統始終為所有的物件維護一個被稱為執行時的型別標識。 這個資訊跟蹤著每個物件所屬的類。虛擬機器利用執行時型別資訊選擇相應的方法執行。 然而, 可以通過專門的 Java 類訪問這些資訊。儲存這些資訊的類被稱為 Class, 這個名 字很容易讓人混淆。Object 類中的 getClass( ) 方法將會返回一個 Class 型別的例項。

   public
static void main(String[] args) throws ClassNotFoundException { // TODO Auto-generated method stub Hero hero = new Hero(); Integer h = new Integer(2); String s = new String("面對疾風"); String s2 = "xueren"; //驗證三種獲取Class 物件的方式 Class class1 = Class.forName("com.yunsi.pojo.Hero"); System.out.println(class1.getName()); System.out.println(s.getClass().getName()); System.out.println(Hero.
class.getName()); System.out.println(); //一個類中只存在一個Class物件,封裝著這個類的所有資訊 System.out.println(s.getClass().hashCode()); System.out.println(s2.getClass().hashCode()); System.out.println(h.getClass().hashCode()); } ​ } ​ //執行結果如下所示 //com.yunsi.pojo.Hero //java.lang.String //com.yunsi.pojo.Hero //366712642 //366712642 //1829164700

獲取Class類的三種方式

  • 物件.getClass

  • Class.forName("String "); //String為某類的報名加類名

  • 類.class

注意

獲得 Class類物件的第三種方法非常簡單。如果 T 是任意的 Java型別(或 void關鍵字), T.class 將代表匹配的類物件。例如: Class dl = Random,class; // if you import java.util Gass cl2 = int.class; Class cl3 = Doublet],class; 請注意,一個 Class 物件實際上表示的是一個型別,而這個型別未必一定是一種類。例如, int 不是類,但 int.class 是一個 Class 型別的物件。

註釋: Class 類實際上是一個泛型類。例如, Employee.class 的型別是 Class<Employee>。 沒有說明這個問題的原因是: 它將已經抽象的概念更加複雜化了。在大多數實際問題 中, 可以忽略型別引數, 而使用原始的 Class 類。

鑑於歷史原 getName 方法在應用於陣列型別的時候會返回一個很奇怪的名字:

  • Double[ ] class.getName( ) 返回“ [Ljava.lang.Double;’’

  • int[ ].class.getName( ) 返回“ [I”

還有一個很有用的方法 newlnstance( ),他是Object類中的方法, 可以用來動態地建立一個類的例項例如, e.getClass0.newlnstance(); 建立了一個與 e具有相同類型別的例項。newlnstance方法呼叫預設的構造器(沒有引數的構 造器)初始化新建立的物件。如果這個類沒有預設的構造器, 就會丟擲一個異常_ 將 forName 與 newlnstance 配合起來使用, 可以根據儲存在字串中的類名建立一個物件

String s = "java.util.Random"; Object m = Class.forName(s).newlnstance(); Q 註釋:如果需要以這種方式向希望按名稱建立的類的構造器提供引數, 就不要使用上面 那條語句, 而必須使用 Constructor 類中的 newlnstance 方法。

利用反射分析類的能力

概述:在java.lang.reflect 包中有三個類 Field、Method 和 Constructor 分別用於描述類的域、 方 法和構造器。

  • Field

    • getName() 返回專案的名稱

    • getType(); 返回所描述域所屬型別的Class物件

    • get(Object obj) 檢視物件域

    • getModifiers();

      • static ( isPublic isPrivate isFinal)

      • static toString();

  • Method

    • getName(); 返回專案的名稱

    • getGenericReturnType() 返回方法的返型別

    • getModifiers(); 返回整數型,用不同的位開關描述public和static這樣的修飾符使用狀況,當沒有這兩個修飾符,則返回值為0

      • static ( isPublic isPrivate isFinal)

      • static toString();

  • Constructor

    • getName() 返回專案的名稱

    • getModifiers();

      • static ( isPublic isPrivate isFinal)

      • static toString();

    • getParameterTypes() 返回一個用於描述引數型別的Class物件的陣列

    • newInstance(); 例項化構造器(Object中的方法)

  • Class

    • getFields();

    • getDeclaredFields()

    • getMethods()

    • getDeclaredMethods()

    • getConstructors()

    • getDeclaredConstructors()

注意: Class類中的getxxx 和getDeclaredxxx 的區別在於前者返回提供的public修飾的域,方法和構造器陣列,其中包含超類的公有成員;後者返回的是全部域,方法和構造器,其中包括private修飾,但不包括超類的成員

在執行時使用反射分析物件

檢視物件域的關鍵方法是 Field類中的 get 方法。如果 f 是一個 Field型別的物件(例如, 通過 getDeclaredFields 得到的物件),obj 是某個包含 f 域的類的物件,f.get(obj) 將返回一個 物件,其值為 obj 域的當前值。這樣說起來顯得有點抽象,這裡看一看下面這個示例的執行。

 Employee harry = new Employee("Harry Hacker", 35000, 10, 1, 1989);
​
 Class cl = harry.getClass(); // the class object representing Employee 
​
Field f = cl.getDeclaredField("name"): // the name field of the Employee class 
​
Object v = f.get(harry); // the value of the name field of the harry object, i.e.,
​
 the String object "Harry Hacker"

實際上,這段程式碼存在一個問題。由於 name 是一個私有域, 所以 get方法將會丟擲一個 IllegalAccessException。只有利用 get 方法才能得到可訪問域的值。除非擁有訪問許可權,否則 Java 安全機制只允許査看任意物件有哪些域, 而不允許讀取它們的值。 反射機制的預設行為受限於 Java 的訪問控制。然而, 如果一個 Java 程式沒有受到安全管理器的控制, 就可以覆蓋訪問控制。 為了達到這個目的, 需要呼叫 Field、Method 或 Constructor 物件的 setAccessible 方法。例如, f.setAtcessible(true); // now OK to call f.get(harry); setAccessible方法是 AccessibleObject 類中的一個方法, 它是 Field、 Method 和 Constructor 類的公共超類。這個特性是為除錯、持久儲存和相似機制提供的;當然,可以獲得就可以設定。呼叫 f.set(obj,value) 可以將 obj 物件的 f 域設定成新值。

呼叫任意方法

在 Method 類中有一個 invoke 方法, 它允許呼叫包裝在當前 Method 物件中 的方法。invoke 方法的簽名是: Object invoke(Object obj, Object... args) 第一個引數是隱式引數, 其餘的物件提供了顯式引數(在 Java SE 5.0 以前的版本中,必須傳遞一個物件陣列, 如果沒有顯式引數就傳遞一個 null)。 對於靜態方法,第一個引數可以被忽略, 即可以將它設定為 null。

invoke方法的引數,一個是Object型別,也就是呼叫該方法的物件,第二個引數是一個可變引數型別,呼叫者是Method的物件