反射可以解決在編譯時無法預知對象和類是屬于那個類的蠢棱,要根據(jù)程序運行時的信息才能知道該對象和類的信息的問題锌杀。在兩個人協(xié)作開發(fā)時,你只要知道對方的類名就可以進行初步的開發(fā)了泻仙。
JAVA反射機制是在運行狀態(tài)中糕再,對于任意一個類,都能夠知道這個類的所有屬性和方法饰豺;對于任意一個對象亿鲜,都能夠調(diào)用它的任意一個方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機制冤吨。
public class Man implements AnimalBaseSkill{
public static String AGE=12;
public int sex=-1;
private String name;
private Man(int sex, String name) {
this.sex = sex;
this.name = name;
}
public Man() {
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void eat() {}
private class Clan {
String clanName="default family";
public Clan(String familyName) {
this.clanName = familyName;
}
public Clan() {
}
public String getClanName() {
return clanName;
}
public void setClanName(String clanName) {
this.clanName = clanName;
}
}
}
一 :獲取類的三種方法
Class.forName(String clazzName)靜態(tài)方法
調(diào)用類的class屬性蒿柳,Person.class返回的就是Person的class對象(推薦使用)
調(diào)用某個對象的getClass()方法
Class class_Man = Class.forName("com.ch.java.reflect.Man");
Class class_Man = Man.class;
Class class_Man =Man.getClass();
二 :獲取私有內(nèi)部類
但是只有方法一可以獲取私有內(nèi)部類:
Class class_Clan=Class.forName("com.ch.java.reflect.Man$Clan");
三 :獲取構(gòu)造器和自己的實例
獲取Class后,然后通過Class獲取構(gòu)造器漩蟆,通過newInstance()就可以獲取該對象:
Constructor constructor=class_Man.getConstructor(null);
Man man= (Man) constructor.newInstance();
四 :獲取內(nèi)部類對象
但是內(nèi)部類的對象要像下面獲取垒探,原因會在(如何獲取類構(gòu)造器?)講解
Constructor constructor=class_Clan.getConstructor(Man.class, String.class); //如果Clan構(gòu)造函數(shù)沒有可以不傳
Object family=constructor.newInstance(man, "123");
五 :獲取類構(gòu)造器
getConstructor(Class...parameterTypes):返回此Class對象對應類的帶指定形參的public構(gòu)造器,返回參數(shù):Connstructor
getConstructors():返回此Class對象對應類的所有public構(gòu)造器怠李,返回參數(shù):Constructor[]
getDeclaredConstructor(Class...parameterTypes):返回此class對象對應類的帶指定參數(shù)的構(gòu)造器圾叼,與構(gòu)造器的訪問權限無關,返回參數(shù):Constructor[]
getDeclaredConstructors():返回此class對象對應類的所有構(gòu)造器捺癞,與構(gòu)造器的訪問權限無關夷蚊,返回參數(shù):Constructor[]
六 :獲取類成員方法
getMethod(String name,Class<?>...parameterTypes):返回此class對象對應類的帶指定形參的public方法,返回參數(shù):Method
Method[] getMethods():返回此class對象所表示的類的所有public方法
Method getDeclaredMethod(string name,Class<?>...parameterTypes):返回此class對象對應類的帶指定形參的方法,與方法訪問權限無關
Method[] getDeclaredMethods():返回此class對象對應類的全部方法髓介,與方法的訪問權限無關
七 :獲取成員變量獲取屬性
Field getField(String name):返回此class對象對應類的指定名稱的public成員變量
getFields():返回此class對象對應類的所有public成員變量惕鼓,返回參數(shù):Field[]
getDeclaredField(String name):返回此class對象對應類的指定名稱的成員變量,與成員變量訪問權限無關唐础。返回參數(shù):Field
getDeclaredFields():返回此class對象對應類的全部成員變量箱歧,與成員變量的訪問權限無關,返回參數(shù):Field[]
Object property = class_Man.get(AGE) :此如果屬性石靜態(tài)的一膨,可直接從class對象中取出呀邢。
八:執(zhí)行方法某對象的方法
public Object invokeMethod(Object owner, String methodName, Object[] args)
執(zhí)行該方法的方法 method.invoke(owner, args)
method.invoke(owner, args):執(zhí)行該Method.invoke方法的參數(shù)是執(zhí)行這個方法的對象owner,和參數(shù)數(shù)組args豹绪,可以這么理解:owner對象中帶有參數(shù)args的method方法价淌。返回值是Object,也既是該方法的返回值。
Method中invoke(Object obj,Object...args)第一個參數(shù)為類的實例输钩,
第二個參數(shù)為相應函數(shù)中的參數(shù).
* provoked by this method fails.
*/
public native Object invoke(Object receiver, Object... args)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException;
/**
public void setHobby(String[] hobby) {
this.hobby = hobby;
}
用Invoke調(diào)用函數(shù)
Class clazz = SimpleBean.class;
//使用無參構(gòu)造函數(shù)實例化bean
SimpleBean sb = (SimpleBean)clazz.newInstance();
//列出類SimpleBean的所有方法
Method[] methods = clazz.getDeclaredMethods(); System.out.println("get methods of class SimpleBean:");
for(Method method : methods) {
if("setHobby".equals(method.getName())) {
//動態(tài)調(diào)用類的方法來為hobby設置值
method.invoke(sb, new Object[]{new String[]{"tennis","fishing"}});
}
八:Filed的get和set方法
get(Object obj) 返回指定(ListenerInfo)對象上此 Field (OnClickListener ) 表示的字段的值豺型。
static class ListenerInfo{
public OnClickListener mOnClickListener;
}
Class listenerInfoClazz = Class.forName("com.View$ListenerInfo");
/*得到View$ListenerInfo類中mOnClickListener屬性*/
Field mOnClickListenerField = listenerInfoClazz.getDeclaredField("mOnClickListener");
//得到Infor中mOnClickListener
OnClickListener mOnClickListener = (OnClickListener) mOnClickListenerField.get(listenerInfoObj);
void set(Object obj, Object value) 將指定對象(ListenerInfo)變量上此 Field (OnClickListener )字段設置為指定的新值仲智。
OnClickListener mOnClickListener = (OnClickListener) mOnClickListenerField.get(listenerInfoObj);
/*使用自定義代理方法*/
System.err.println("mOnClickListener :"+mOnClickListener);
OnClickListener mOnClickListenerProxy=new OnClickListenerProxy(mOnClickListener);
System.out.println("mOnClickListenerProxy :"+mOnClickListenerProxy);
//更換
mOnClickListenerField.set(listenerInfoObj, mOnClickListenerProxy);