反射工具主要支援物件序列化、Java Beans、RMI 等特性,鮮少直接使用。但常需動態提取類別相關資訊——查看原始碼或文件只能看到該類別定義/覆寫的方法,基類資訊拿不到。反射可自動展示完整介面。
//: ShowMethods.java
import java.lang.reflect.*;
public class ShowMethods {
static final String usage = "usage: \nShowMethods qualified.class.name\nTo show all methods in class or: \nShowMethods qualified.class.name word\nTo search for methods involving 'word'";
public static void main(String[] args) {
if(args.length < 1) { System.out.println(usage); System.exit(0); }
try {
Class c = Class.forName(args[0]);
Method[] m = c.getMethods();
Constructor[] ctor = c.getConstructors();
if(args.length == 1) {
for (int i = 0; i < m.length; i++) System.out.println(m[i].toString());
for (int i = 0; i < ctor.length; i++) System.out.println(ctor[i].toString());
} else {
for (int i = 0; i < m.length; i++)
if(m[i].toString().indexOf(args[1]) != -1) System.out.println(m[i].toString());
for (int i = 0; i < ctor.length; i++)
if(ctor[i].toString().indexOf(args[1]) != -1) System.out.println(ctor[i].toString());
}
} catch (ClassNotFoundException e) { System.out.println("No such class: " + e); }
}
} ///:~
Class.getMethods()/getConstructors() 回傳 Method/Constructor 陣列。toString() 產生完整方法簽名字串。執行期提取資訊屬「反射」技術。
執行 java ShowMethods ShowMethods 可見編譯器自動合成的預設公用建構子。若改為非 public 類別,合成建構子不會出現(自動獲得與類別相同存取權限)。
//: ShowMethodsClean.java
import java.lang.reflect.*;
import java.io.*;
public class ShowMethodsClean {
// ... usage 同前 ...
public static void main(String[] args) {
// ... 取得 Class、Method[]、Constructor[] ...
// 轉換為清理後字串陣列
String[] n = new String[m.length + ctor.length];
for(int i = 0; i < m.length; i++) {
String s = m[i].toString();
n[i] = StripQualifiers.strip(s);
}
for(int i = 0; i < ctor.length; i++) {
String s = ctor[i].toString();
n[i + m.length] = StripQualifiers.strip(s);
}
// ... 輸出或搜尋 ...
}
}
class StripQualifiers {
private StreamTokenizer st;
public StripQualifiers(String qualified) {
st = new StreamTokenizer(new StringReader(qualified));
st.ordinaryChar(' '); // 保留空格
}
public String getNext() { /* ... 解析 token ... */ }
public static String strip(String qualified) {
StripQualifiers sq = new StripQualifiers(qualified);
String s = "", si;
while((si = sq.getNext()) != null) {
int lastDot = si.lastIndexOf('.');
if(lastDot != -1) si = si.substring(lastDot + 1);
s += si;
}
return s;
}
} ///:~
利用 StreamTokenizer 解析並移除 java.lang 等限定詞,輸出更易讀。第 17 章提供 GUI 版本供開發時快速查詢。