Java Reflection API提供對JVM中的類,接口和對象的深入洞察。開發者通常使用API來完成以下的任務,這解釋了為什麼總是使用開發工具,例如debugger和Integrated Development Environments (IDEs):
決定一個對象的類。
獲得關於一個類的modifiers, fIElds, methods, constructors, etc的信息。
獲得關於一個接口的常量和方法聲明。
創建一個類的instance,這個類的名字直到運行時才知道,而且在設計時間時可用或是作為一個運行參數被提供。
獲得並設置一個對象的field值,即使fIEld的名字直到運行時程序才會知道。
調用一個對象上的方法,即使這個方法直到運行時才會知道。
Reflection的具體使用是在JavaBeans中,這裡你可以通過一個構建工具來操作軟件組件。工具使用reflection來獲取Java 組件(類)的屬性,因為它們是動態加載。
使用Reflection檢索Class Behavior
為了了解你如何使用Reflection來確定一個類行為,考慮以下Employee class的簡單例子:
public class Employee
{
public String empNum;
public String empName;
public Employee()
{
this( "1", "King");
}
public Employee(String empNum, String empName)
{
empNum = empNum;
empName = empName;
}
public String toString()
{
return "Employee Details: EmpNumber: " + empNum + ",
EmpName: "+ empNum;
}
}
import Java.lang.reflect.ModifIEr;
public class AnalyzeClass
{
public static void main(String[] args)
{
Employee employee = new Employee();
Class klass = employee.getClass();
System.out.println( "Class name: " + klass.getName());
System.out.println(
"Class super class: " + klass.getSuperclass());
int mods = klass.getModifIErs();
System.out.println(
"Class is public: " + ModifIEr.isPublic(mods));
System.out.println(
"Class is final: " + ModifIEr.isFinal(mods));
System.out.println(
"Class is abstract: " + ModifIEr.isAbstract(mods));
}
}
編譯ModifIEr classes並執行AnalyzeClass產生如下結果:
Class name: Employee
Class super class: class Java.lang.Object
Class is public: true
Class is final: false
Class is abstract: false
這個基本上是Employee class的一個引用,所以可以檢索它的所有屬性。還需要更有說服力的嗎?看另外一個關於Method class的例子:
import Java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
但你編譯這個代碼的時候,用帶有已知類的一個argument來調用它…
java DumpMethods Java.util.Stack
…你得到以下的結果:
public synchronized java.lang.Object Java.util.Stack.pop()
public java.lang.Object java.util.Stack.push(Java.lang.Object)
public boolean Java.util.Stack.empty()
public synchronized java.lang.Object Java.util.Stack.peek()
public synchronized int java.util.Stack.search(Java.lang.Object)
在上面的結果中列出了所有java.util.Stack class的方法。Method 是在Java.lang.reflect中的一個類,負責產生這個結果。
使用Reflection檢索Attributes
一個類有其他的一些實體,除了迄今為止你看到的那些。變量怎麼樣,舉個例子?你可以使用reflection來獲取這些實體的具體輸出。這裡是使用一個FIEld class的另一個例子:
import Java.lang.reflect.*;
public class DumpFIElds {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Field[] fields = c.getFIElds();
for (int i = 0; i < fIElds.length; i++)
System.out.println(fIElds[i].toString());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
當你編譯這個代碼的時候並用Employee的一個argument執行它…
Java DumpFIElds Employee
你得到以下的結果:
public Java.lang.String Employee.empNum
public Java.lang.String Employee.empName
這個結果列出所有屬於該類的fIElds和ttributes。
使用Reflection檢索Constructors
這個Constructor類的例子將幫助完成對各種constructors運用的理解,以及如何使用它們。
import Java.lang.reflect.*;
public class DumpConstructors {
public static void main(String args[])
{
try {
Class c = Class.forName(args[0]);
Constructor[] constructor = c.getConstructors();
for (int i = 0; i < constructor.length; i++)
{
System.out.println(constructor[i].toString());
//To print the parameter types
Class pvec[] = constructor[i].getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #" + j + " "
+ pvec[j]);
}
}
catch (Throwable e) {
System.err.println(e);
}
}
}
當你編譯這個代碼的時候並用Employee的一個argument執行它…
Javac DumpConstructors Employee
…你得到以下的結果:
public Employee(java.lang.String,Java.lang.String)
param #0 class Java.lang.String
param #1 class Java.lang.String
public Employee()
分析結果的時候你會發現Employee類有兩個constructor。第一個是帶參數的constructor(你也可以看到參數類型)。第二個沒有采用任何參數,結果是不言而喻的。
使用Reflection在運行時執行Class Methods
假設你有一個類並想要在運行的時候使用它。下列代碼顯示你如何加載這個類並在運行時執行一個所期望的方法。這裡假設的是那個方法的名字是setPropertIEs而且采用Java.util.PropertIEs類型的一個argument。
Class newClass = null;
Method getInstanceMethod = null;
Properties prop = new PropertIEs();
prop.put("argName", "argValue");
try
{
Object obj = newClass.newInstance();
getInstanceMethod = newClass.getMethod("setPropertIEs",
new Class[]{new PropertIEs().getClass()});
}
catch (Exception ex)
{
//Exception in loading Class:" + ex.getMessage();
}
這些工具讓一個IDE開發者很容易適應Java作為一個支持編程的語言。