前言:本文主要介紹反射的經常使用的構造函數,成員變量,成員方法的使用,從網絡上搜尋了一些資料,自己寫了列子,主要為閱讀者初級使用反射做指導。
一、Class類的對象
獲得Class對象的方法
下表列出了幾種得到Class類的方法,以供大家參考。
Class object 誕生管道 | 示例 |
運用getClass() 注:每個class 都有此函數 | String str = "abc"; Class c1 = str.getClass(); |
運用 Class.getSuperclass() | Button b = new Button(); Class c1 = b.getClass(); Class c2 = c1.getSuperclass(); |
運用static method Class.forName() (最常被使用) | Class c1 = Class.forName ("java.lang.String"); Class c2 = Class.forName ("java.awt.Button"); Class c3 = Class.forName ("java.util.LinkedList$Entry"); Class c4 = Class.forName ("I"); Class c5 = Class.forName ("[I"); |
運用 .class 文法 | Class c1 = String.class; Class c2 = java.awt.Button.class; Class c3 = Main.InnerClass.class; Class c4 = int.class; Class c5 = int[].class; |
運用 primitive wrapper classes 的TYPE 文法 | Class c1 = Boolean.TYPE; Class c2 = Byte.TYPE; Class c3 = Character.TYPE; Class c4 = Short.TYPE; Class c5 = Integer.TYPE; Class c6 = Long.TYPE; Class c7 = Float.TYPE; Class c8 = Double.TYPE; Class c9 = Void.TYPE; |
擷取Class對象的一些基本資訊
如下表。
Java class 内部子產品 | Java class 内部子產品說明 | 相應之Reflection API,多半為Class methods。 | 傳回值類型(return type) |
package | class隸屬哪個package | getPackage() | Package |
import | class導入哪些classes | 無直接對應之API。可間接擷取。 | |
modifier | class(或methods, fields)的屬性 | int getModifiers() Modifier.toString(int) Modifier.isInterface(int) | int String bool |
class name or interface name | class/interface | 名稱getName() | String |
type parameters | 參數化類型的名稱 | getTypeParameters() | TypeVariable <Class>[] |
base class | base class(隻可能一個) | getSuperClass() | Class |
implemented interfaces | 實作有哪些interfaces | getInterfaces() | Class[] |
inner classes | 内部classes | getDeclaredClasses() | Class[] |
outer class | 如果我們觀察的class 本身是inner classes,那麼相對它就會有個outer class。 | getDeclaringClass() | Class |
上表中,列出了一些Java class内部資訊的擷取方式。所采用的方法幾乎都是調用Class對象的成員方法(由此你就可以了解到Class類的用處了吧)。
二、類中最重要的三個資訊
構造函數
擷取構造函數的方法有以下幾個:
ConstructorgetConstructor(Class[] params)
Constructor[]getConstructors()
ConstructorgetDeclaredConstructor(Class[] params)
Constructor[]getDeclaredConstructors()
Class[] params為目标類的構造函數參數類型數組,具體見以下的舉例
不帶Declared關鍵字的函數(如:getConstructor)隻能擷取到公有的構造函數,
帶Declared關鍵字的函數(如:getDeclaredConstructor)能擷取到飛共有的構造函數,即所有通路保護機制的構造函數。
成員函數
和擷取構造函數的方法類似,擷取成員函數的方法有以下一些:
MethodgetMethod(String name, Class[] params)
Method[]getMethods()
MethodgetDeclaredMethod(String name, Class[] params)
Method[]getDeclaredMethods()
其中需要注意,String name參數,需要寫入方法名。關于通路權限和确定性的問題,和構造函數基本一緻。
成員變量
擷取成員變量的方法與上面兩種方法類似,具體如下:
FieldgetField(String name)
Field[]getFields()
FieldgetDeclaredField(String name)
Field[]getDeclaredFields()
其中,String name參數,需要寫入變量名。關于通路權限和确定性的問題,與前面兩例基本一緻。
三、使用舉例
我們舉一個兩個數相加的列子
MathPlus類代碼:
package cn.cq.shenyun;
public class MathPlus {
public int num1=0;
public int num2=0;
//預設構造函數
public MathPlus(){
}
//帶兩個整形參數的構造函數
public MathPlus(int nummber1,int nummber2){
num1=nummber1;
num2=nummber2;
}
//将對象内的兩個成員相繼傳回
public int add1(){
return num1+num2;
}
//将傳入的兩整形參數相加傳回
public int add2(int nummber1,int nummber2){
return nummber1+nummber2;
}
}
MathMain類:該類是主函數所在類,利用反射操作MathPlus類
package cn.cq.shenyun;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class MathMain {
public static void main(String[] args) {
test1();
test2();
test3();
test4();
}
//用無參構造函數構造對象,再調用無參方法add1
public static void test1(){
try {
//擷取Class
Class<?> cls = Class.forName("cn.cq.shenyun.MathPlus");
//用預設構造函數構造對象
Constructor<?> con=cls.getConstructor();
Object mathobj=con.newInstance();
//如果是用無參構造,可直接用Class的newInstance方法,都夠構造對象
//Object mathobj=cls.newInstance();
//調用無參數對象方法add1
Method method=cls.getMethod("add1");//指定調用的方法 add1
int result=(Integer)method.invoke(mathobj);//調用mathobj1 的add1方法
System.out.println("----test1 用無參構造函數構造對象,再調用無參方法add1----");
System.out.println(" test1 result="+result);
}catch (Exception e) {
}
}
//利用反射改變對象的成員變量
public static void test2(){
try{
//擷取Class
Class<?> cls = Class.forName("cn.cq.shenyun.MathPlus");
//用預設構造函數構造對象
Constructor<?> con=cls.getConstructor();
Object mathobj=con.newInstance();
//修改mathobj對象中num1的值
Field field1=cls.getDeclaredField("num1");
field1.setInt(mathobj, 2);
//修改mathobj對象中num2的值
Field field2=cls.getDeclaredField("num2");
field2.setInt(mathobj, 3);
//調用無參數對象方法add1
Method method=cls.getMethod("add1");//指定調用的方法 add1
int result=(Integer)method.invoke(mathobj);//調用mathobj1 的add1方法
//System.out.println("test2 number1="+field1.getInt(mathobj));
//System.out.println("test2 number2="+field2.getInt(mathobj));
System.out.println("----test2 利用反射改變對象的成員變量----");
System.out.println(" test2 result="+result+",number1="+field1.getInt(mathobj)+",number2="+field2.getInt(mathobj));
}catch (Exception e) {
e.printStackTrace();
}
}
//調用有參構造函數
public static void test3(){
try{
//擷取Class
Class<?> cls = Class.forName("cn.cq.shenyun.MathPlus");
//設定構造函數的參數類型
Class<?>[] parTypes=new Class<?>[2];
parTypes[0]=int.class;
parTypes[1]=int.class;
//擷取構造器
Constructor<?> con=cls.getConstructor(parTypes);//----------------重點注意,參數變化了
//初始化構造參數
Object[] pars=new Object[2];
pars[0]=4;
pars[1]=5;
//構造對象
Object mathobj=con.newInstance(pars); //----------------重點注意,參數變化了
//調用add1
Method method=cls.getMethod("add1");//指定調用的方法 add1
int result=(Integer)method.invoke(mathobj);//調用mathobj 的add1方法
System.out.println("----test3 調用有參構造函數----");
System.out.println(" test3 result="+result);
}catch (Exception e) {
}
}
//調用有參數的函數 add2
public static void test4(){
try{
//擷取Class
Class<?> cls = Class.forName("cn.cq.shenyun.MathPlus");
//用預設構造函數構造對象
Constructor<?> con=cls.getConstructor();
Object mathobj=con.newInstance();
//調用add2
Class<?>[] parTypes=new Class<?>[2];
parTypes[0]=int.class;
parTypes[1]=int.class;
Method method=cls.getMethod("add2",parTypes);//指定調用的方法 add2
Object[] pars=new Object[2];
pars[0]=6;
pars[1]=7;
int result=(Integer)method.invoke(mathobj,pars);//調用mathobj 的add2方法
System.out.println("----test4 調用有參數的函數 add2----");
System.out.println(" test4 result="+result);
}catch (Exception e) {
}
}
}
運作結果:
代碼下載下傳位址
百度網盤分享位址:http://pan.baidu.com/share/link?shareid=3185562225&uk=4093749335