選擇自 lxblg 的 Blog
java的反射技術功能十分強大,整理一些資料!!
(如需轉載,請註明出處!)
Lesson: 檢測類examing class
1.Retrieving Class Objects
擷取一個Class對象(metadata)
a,從對象的執行個體擷取。
Class c = mystery.getClass();//(return Class)
b,從子類的執行個體擷取
TextField t = new TextField();
Class c = t.getClass();
Class s = c.getSuperclass();
c,知道類名,則可以把.class加入到名字之後來擷取。
Class c = java.awt.Button.class;
d,如果類名在編譯時間是未知的,則可以使用Class.forName()方法來擷取.
Class c = Class.forName(classString);
2.Getting the Class Name
擷取類名稱
c.getName();
例如:
import java.lang.reflect.*;
import java.awt.*;
class SampleName {
public static void main(String[] args) {
Button b = new Button();
printName(b);
}
static void printName(Object o) {
Class c = o.getClass();
String s = c.getName();
System.out.println(s);
}
}
3.Discovering Class Modifiers
檢索修改符
a.通過getModifiers()方法擷取一個整型標識值。
b.通過java.reflect.Modifier對象的isPublic, isAbstract, 和 isFinal方法判斷此值.
例如:
import java.lang.reflect.*;
import java.awt.*;
class SampleModifier {
public static void main(String[] args) {
String s = new String();
printModifiers(s);
}
public static void printModifiers(Object o) {
Class c = o.getClass();
int m = c.getModifiers();
if (Modifier.isPublic(m))
System.out.println("public");
if (Modifier.isAbstract(m))
System.out.println("abstract");
if (Modifier.isFinal(m))
System.out.println("final");
}
}
4.Finding Superclasses
檢索父類
例如:
import java.lang.reflect.*;
import java.awt.*;
class SampleSuper {
public static void main(String[] args) {
Button b = new Button();
printSuperclasses(b);
}
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();
}
}
}
5.Identifying the Interfaces Implemented by a Class
檢索指定類實現的介面
例如:
import java.lang.reflect.*;
import java.io.*;
class SampleInterface {
public static void main(String[] args) {
try {
RandomAccessFile r = new RandomAccessFile("myfile", "r");
printInterfaceNames(r);
} catch (IOException e) {
System.out.println(e);
}
}
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);
}
}
}
6.Examining Interfaces
判定一個類是不是介面
import java.lang.reflect.*;
import java.util.*;
class SampleCheckInterface {
public static void main(String[] args) {
Class thread = Thread.class;
Class runnable = Runnable.class;
verifyInterface(thread);
verifyInterface(runnable);
}
static void verifyInterface(Class c) {
String name = c.getName();
if (c.isInterface()) {
System.out.println(name + " is an interface.");
} else {
System.out.println(name + " is a class.");
}
}
}
如:c.isInterface()
7.Identifying Class Fields
找出指定類所有的域成員
每個資料成員可以用java.reflect.Field來封閉其名稱,類型,修改符的集合。
也可以通過相應的方法擷取或設定到該成員的值。
如:
import java.lang.reflect.*;
import java.awt.*;
class SampleField {
public static void main(String[] args) {
GridBagConstraints g = new GridBagConstraints();
printFieldNames(g);
}
static void printFieldNames(Object o) {
Class c = o.getClass();
Field[] publicFields = c.getFields();
for (int i = 0; i < publicFields.length; i++) {
String fieldName = publicFields[i].getName();
Class typeClass = publicFields[i].getType();
String fieldType = typeClass.getName();
System.out.println("Name: " + fieldName +
", Type: " + fieldType);
}
}
}
8.Discovering Class Constructors
檢索指定類的建構函式
當建立一個類的執行個體時,是通過檢造方法來作的,這種方法可以被重載。
每一個構造方法可以用類Constructor來描述,,包括名稱,修飾符,參數類型(Class[]),和異常列表。
可以通過一個Class的getConstructors方法擷取到該類的Constructor數組。
常式:
import java.lang.reflect.*;
import java.awt.*;
class SampleConstructor {
public static void main(String[] args) {
Rectangle r = new Rectangle();
showConstructors(r);
}
static void showConstructors(Object o) {
Class c = o.getClass();
Constructor[] theConstructors = c.getConstructors();
for (int i = 0; i < theConstructors.length; i++) {
System.out.print("( ");
Class[] parameterTypes =
theConstructors[i].getParameterTypes();
for (int k = 0; k < parameterTypes.length; k ++) {
String parameterString = parameterTypes[k].getName();
System.out.print(parameterString + " ");
}
System.out.println(")");
}
}
}
9.Obtaining Method Information
檢索方法
可以找到隸屬於一個類的所有方法,通過getMethods包含Method數組,進而得到該方法的傳回型別,修飾符,方法名稱,參數列表
步驟:
a.指定類的Class Object
b.getMethods()擷取Method[]對象
c,遍曆該數組對象
常式:
import java.lang.reflect.*;
import java.awt.*;
class SampleMethod {
public static void main(String[] args) {
Polygon p = new Polygon();
showMethods(p);
}
static void showMethods(Object o) {
Class c = o.getClass();
Method[] theMethods = c.getMethods();
for (int i = 0; i < theMethods.length; i++) {
String methodString = theMethods[i].getName();
System.out.println("Name: " + methodString);
String returnString =
theMethods[i].getReturnType().getName();
System.out.println(" Return Type: " + returnString);
Class[] parameterTypes = theMethods[i].getParameterTypes();
System.out.print(" Parameter Types:");
for (int k = 0; k < parameterTypes.length; k ++) {
String parameterString = parameterTypes[k].getName();
System.out.print(" " + parameterString);
}
System.out.println();
}
}
}
Lesson:2 處理對象
1.Creating Objects
一般情況下,建立一個對象用以下方法
Rectangle r = new Rectangle();
但如果你正在開發一個development tools,在運行之前或許不知道要產生對象的類。
所以要像下面這樣來建立對象:
String className;
// . . . load className from the user interface
Object o = new (className); // WRONG!
但以上是錯誤的。
正確的方法是使用類的反射特性:
1)Using No-Argument Constructors
例如:
Class classDefinition = Class.forName(className);//指定類的運行期執行個體
object = classDefinition.newInstance();//調用無參建構函式來產生指定類的執行個體。
2)Using Constructors that Have Arguments
這個技術要用到如下步驟:
a,建立一個Class對象
b,建立一個Constructor對象,getConstructor(Class[] params)方法,參數是一個與構造方法相適合的Class 數組.
c,在Constructor對象上調用newInstance方法來產生一個對象,參數 是一個object數組與這個構造方法相配備。
例如:
import java.lang.reflect.*;
import java.awt.*;
class SampleInstance {
public static void main(String[] args) {
Rectangle rectangle;
Class rectangleDefinition;
Class[] intArgsClass = new Class[] {int.class, int.class};
Integer height = new Integer(12);
Integer width = new Integer(34);
Object[] intArgs = new Object[] {height, width};
Constructor intArgsConstructor;
try {
//1.
rectangleDefinition = Class.forName("java.awt.Rectangle");
//2.
intArgsConstructor =
rectangleDefinition.getConstructor(intArgsClass);//找到指定的構造方法
//3.
rectangle =
(Rectangle) createObject(intArgsConstructor, intArgs);//構造方法描述對象,object[]
} catch (ClassNotFoundException e) {
System.out.println(e);
} catch (NoSuchMethodException e) {
System.out.println(e);
}
}
public static Object createObject(Constructor constructor,
Object[] arguments) {
System.out.println ("Constructor: " + constructor.toString());
Object object = null;
try {
object = constructor.newInstance(arguments);
System.out.println ("Object: " + object.toString());
return object;
} catch (InstantiationException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (IllegalArgumentException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
return object;
}
}
2。Getting Field Values
If you are writing a development tool such as a debugger, you must be able to obtain field values. This is a three-step process:
如果要作一個開發工具像debugger之類的,你必須能發現filed values,以下是三個步驟:
a.建立一個Class對象
b.通過getField 建立一個Field對象
c.調用Field.getXXX(Object)方法(XXX是Int,Float等,如果是對象就省略;Object是指實
例).
例如:
import java.lang.reflect.*;
import java.awt.*;
class SampleGet {
public static void main(String[] args) {
Rectangle r = new Rectangle(100, 325);
printHeight(r);
}
static void printHeight(Rectangle r) {
Field heightField;
Integer heightValue;
Class c = r.getClass();
try {
heightField = c.getField("height");
heightValue = (Integer) heightField.get(r);
System.out.println("Height: " + heightValue.toString());
} catch (NoSuchFieldException e) {
System.out.println(e);
} catch (SecurityException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
}
}
}
3。Setting Field Values
a.建立一個Class對象
b.通過getField 建立一個Field對象
c.調用Field.set(Object,withparam)方法(XXX是Int,Float等,如果是對象就省略;Object是指執行個體,withparam指和這個欄位相區配的欄位。
import java.lang.reflect.*;
import java.awt.*;
class SampleSet {
public static void main(String[] args) {
Rectangle r = new Rectangle(100, 20);
System.out.println("original: " + r.toString());
modifyWidth(r, new Integer(300));
System.out.println("modified: " + r.toString());
}
static void modifyWidth(Rectangle r, Integer widthParam ) {
Field widthField;
Integer widthValue;
Class c = r.getClass();
try {
widthField = c.getField("width");
widthField.set(r, widthParam);
} catch (NoSuchFieldException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
}
}
}
4。調用指定的方法
a.建立一個Class對象
b.建立一個方法對象method,getMethod(String methodName,Class[])方法
c.調方法對象,method.invoke(object,Object[]),兩個參數,第一個是指調用方法所屬於的對象,第二個是傳遞的值對象列表。
The sample program that follows shows you how to invoke a method dynamically. The program retrieves the Method object for the String.concat method and then uses invoke to concatenate two String objects.
//
import java.lang.reflect.*;
class SampleInvoke {
public static void main(String[] args) {
String firstWord = "Hello "; //指定類的執行個體
String secondWord = "everybody.";//變元
String bothWords = append(firstWord, secondWord);
System.out.println(bothWords);
}
public static String append(String firstWord, String secondWord) {
String result = null;
Class c = String.class;
Class[] parameterTypes = new Class[] {String.class};
Method concatMethod;
Object[] arguments = new Object[] {secondWord};
try {
concatMethod = c.getMethod("concat", parameterTypes);//擷取到方法對象
result = (String) concatMethod.invoke(firstWord, arguments);//調用
} catch (NoSuchMethodException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
return result;
}
}