Java looking at Java
Java的一個很不尋常的能力,它允許一個程序檢查自己你可以確定一個對象所屬的類型
你可以查看一個類的全部內容,它們的訪問修飾符、父類、字段、構造函數、方法
你可以查看一個接口的內容
即使在編寫代碼的時候你不知道事物的名字你也可以做到:
創建一個類的實例
取得和設置一個實例的變量
調用一個對象的一個方法
創建和操作數組
我猜它之所以被稱為“反射”是因為它允許一個Java應用程序像“在鏡子里”看到自己一樣。
What is reflection for?
在“平常”的程序中你可能用不到反射如果你是在使用應用程序來操作應用程序,那你就需要使用反射了。
典型的應用:
一個類型查看器
一個調試程序
一個GUI創建器
一個IDE,比喻說BlueJ或Eclipse
IDE
有需要的IDE本身就是用Java編寫的—它們可以做什么?編譯一個程序(簡單—只是一個系統調用)
編譯后加載進你的系統
弄清楚你都有些什么類,它們的構造函數和方法
執行你的main方法
替你創建對象,即使現在沒有運行main方法
為對象傳遞信息,并顯示結果
這些所有的功能,除了編譯都是使用反射做到的
Class 類
要發現一個具體的類的信息,首先要取得它的Class 對象如果你有一個 obj 對象,你可以通過下面的方式來取得它的class對象
Class c = obj.getClass();
你可以通過一個class的實例c 取得它的父類
Class sup = c.getSuperclass();
如果你已經知道一個類在編譯時候的名字 (比喻說, Button) ,你可以通過下面這樣的簡單方法取得class對象
Class c = Button.class;
如果你知道一個類在運行期的名字(比喻說,一個String類型變量str),你可以通過下面的方法取得類對象
Class c = Class.forName(str);
取得類的名字
如果你已經有了一個class對象c,你可以通過下面的方法取得類的名字 c.getName()getName 取得類的全路徑名字; 比喻說,
Class c = Button.class;
String s = c.getName();
System.out.println(s);
會輸出
java.awt.Button
類 Class 和它的方法都是在 java.lang中,所以不需要使用import使其可用。
取得所有的父類
getSuperclass() 返回一個 Class 對象 (或者 null 如果你在 Object上使用的話,它是沒有父類的 )下面的代碼來自Sun的入門指南:
static void printSuperclasses(Object o) {
Class subclass = o.getClass();
Class superclass = subclass.getSuperclass();
while (superclass != null) {
String className = superclass.getName();
System.out.println(className);
subclass = superclass;
superclass = subclass.getSuperclass();
}
}
取得類的修飾符I
Class對象有一個實例方法 getModifiers() ,它返回一個int型的值為了“解釋” int 型的結果,我們要用到Modifier類的一些方法,它們位于 java.lang.reflect, 所以:
import java.lang.reflect.*;
現在我們就可以做下面的事情了:
if (Modifier.isPublic(m)) {
System.out.println("public");
}
取得類的修飾符II
Modifier 包含下面的一些方法 (只列出部分):public static boolean isAbstract(int)
public static boolean isFinal(int)
public static boolean isInterface(int)
public static boolean isPrivate(int)
public static boolean isProtected(int)
public static boolean isPublic(int)
public static String toString(int)
這會返回一個如下所示的字符串
"public final synchronized strictfp"
取得接口
一個類可以實現0個或多個接口getInterfaces() 返回一個 Class 對象的數組
這些是類實現的一些接口
下面的代碼來自Sun的入門指南:
static void printInterfaceNames(Object o) {
Class c = o.getClass();
Class[ ] theInterfaces = c.getInterfaces();
for (int i = 0; i < theInterfaces.length; i++) {
String interfaceName = theInterfaces[i].getName();
System.out.println(interfaceName);
}
}
注意:零長度數組在Java中是合法的
判斷類和接口
Class 類既能代表類也能代表接口要確定一個給定的 Class 對象 c 是否是一個是接口,可以使用 c.isInterface()
要研究class對象的更多內容的話,你可以使用下面這些方法:
getModifiers()
getFields() // "fields" == "instance variables"
getConstructors()
getMethods()
isArray()
取得字段
public Field[] getFields() throws SecurityException返回一個public的字段數組 (變量)
數組的長度允許是0
字段的組織順序沒有任何的規則
本身定義的和通過繼承的來的變量都被返回,但是不包含 static 變量
public Field getField(String name)
throws NoSuchFieldException, SecurityException
返回指定名稱的 public 字段
如果沒有直接的字段被發現,那父類或者接口被遞歸的查詢
使用字段 I
如果 f 是 Field 對象, 那么f.getName() 返回字段的簡單的名字
f.getType() 返回字段的類型 (Class)
f.getModifiers() 返回字段的Modifier
f.toString() 返回一個包含了訪問修飾符,類型,和全路徑字段名字的字符串
例如: public java.lang.String Person.name
f.getDeclaringClass() 返回定義字段的類的 Class 對象
使用字段 II
obj 對象的字段的值可以使用下面的方式進行操作:boolean f.getBoolean(obj),
int f.getInt(obj),
double f.getDouble(obj),
等等,返回字段的值,假設它是那個類型或者可以擴展成那個型
Object f.get(obj) 返回一個字段的值,假設它是一個對象
void f.set(obj, value),
void f.setBoolean(obj, bool),
void f.setInt(obj, i),
void f.getDouble(obj, d),等等,設置一個字段的值
構造函數
如果 c 是一個構造函數,那么c.getName() 返回構造函數的名字,與類的名字完全一致
c.getDeclaringClass() 返回構造函數被聲明的 Class 對象
c.getModifiers() 返回構造函數的 Modifier
c.getParameterTypes() 返回一個Class 對象數組, 以聲明的順序
c.newInstance(Object[] initargs) 創建被返回一個c類的實例對象
需要使用簡單類型的地方會被自動的轉換
方法
public Method[] getMethods()throws SecurityException
返回一個 Method 對象數組
返回的是類或接口的 public 成員方法,同時也包含繼承的來的方法
返回的方法沒有任何的順序
public Method getMethod(String name,
Class[] parameterTypes)
throws NoSuchMethodException, SecurityException
Method 中的方法 I
getDeclaringClass()返回一個Class 對象,它代表了這個Method 對象所被聲明的類或接口
getName()
返回代表這個Method 對象的名字,以字符串的方式
getModifiers()
返回代表這個Method 對象的修飾符,以整型的方式
getParameterTypes()
返回這個Method 對象所需要的參數的 Class 對象數組,以聲明的順序出現
Method 中的方法 II
getReturnType()返回代表這個Method 對象的返回值的一個 Class對象名字
toString()
返回一個代表這個Method 對象的字符串,通常情況下會很長
public Object invoke(Object obj, Object[] args)
在特定的對象上使用特定的參數,執行這個Method對象所代表的方法
個別的參數會被自動轉換來實現一些對基本數據類型的需要
數組 I
可以采用下面的方法來判斷一個obj 對象是不是一個數組Class c = obj.getClass();
c.isArray()
要取得這個數組的元素的類型可以使用,
c.getComponentType()
如果c不是一個數組的話會返回一個 null
在java.lang.reflect 包中包含了一個 Array 類,它提供了一些 static 方法來操作數組
數組 II
要創建一個數組,Array.newInstance(Class componentType, int size)
返回一個新創建的數組Object對象,
你可以把它造型成你想要的類型
componentType 本身就可以是一個數組
這會產生一個多維數組
維數的最大限制一般在255
Array.newInstance(Class componentType, int[] size)
返回一個新創建的多維數組Object對象 (使用 size.length 維度)
數組 III
得到數組元素的值Array.get(Object array, int index) 返回一個 Object
Array.getBoolean(Object array, int index) 返回一個 boolean
Array.getByte(Object array, int index) 返回一個 byte
等等.
往數組中保存值,
Array.set(Object array, int index, Object value)
Array.setBoolean(Object array, int index, boolean z)
Array.setByte(Object array, int index, byte b)
等等.
結束語
很多方法都有自己的異常,我在這里沒有描述要查看詳情,你參照Java API
反射在“平常”的程序中用不到,可是你真的需要它的時候卻是不可替代的。
一個相關的話題-類的加載器(class loaders)—Java把需要的類讀進內存
你可以編寫你自己的加載器
這是別的大多數語言不包含的一種功能
| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
25 | 26 | 27 | 28 | 29 | 30 | 31 | |||
1 | 2 | 3 | 4 | 5 | 6 | 7 | |||
8 | 9 | 10 | 11 | 12 | 13 | 14 | |||
15 | 16 | 17 | 18 | 19 | 20 | 21 | |||
22 | 23 | 24 | 25 | 26 | 27 | 28 | |||
29 | 30 | 1 | 2 | 3 | 4 | 5 |
常用鏈接
留言簿(4)
隨筆檔案
搜索
最新評論

- 1.?re: 會議室預定系統(java簡易控制臺版--access數據庫)
- 很不錯,謝謝你了
- --張巧玲
- 2.?re: 會議室預定系統(java簡易控制臺版--access數據庫)[未登錄]
- 請問如何使用呀!
- --chenguo