2022-07-29

反射的基本使用方法

Java反射用的很多,像Retrofit趁怔、Dagger湿硝、Hook、插件化等等很多地方都有用到润努,掌握J(rèn)ava反射的使用十分必要关斜,了解反射原理就更好了。這里就簡(jiǎn)單的介紹下反射的基本用法铺浇。

先把Student.class貼一下

@ClassAnnotation(value = 20)
public class Student {
    @FieldAnnotation
    public static int staticFiled;
    public static final int FINAL_FILED = 100;
    private String name;
    public int age;

    @ConstructorAnnotation(value = 40)
    public Student() {
    }

    private Student(int age) {
        this.age = age;
        System.out.println("Constructor age!");
    }

    private Student(String name) {
        this.name = name;
        System.out.println("Constructor name!");
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Constructor name & age!");
    }

    public String getName() {
        return name;
    }

    @MethodAnnotation
    public void setName(String name) {
        this.name = name;
        System.out.println("invoke public Method!");
    }

    private int getAge() {
        return age;
    }

    private void setAge(int age) {
        this.age = age;
        System.out.println("invoke private Method!");
    }

    public static void staticMethod() {
        System.out.println("invoke static Method!");
    }
}
三種反射方法
//方式一
try {
    Class<?> clazz1 = Class.forName("com.example.myapplication.reflection.Student");
    System.out.println("Class.forName: " + clazz1.getName());
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

//方式二
Class<Student> clazz2 = Student.class;
System.out.println("Student.class: " + clazz2.getName());

//方式三
Student student = new Student();
Class<? extends Student> clazz3 = student.getClass();
System.out.println("student.getClass(): " + clazz3.getName());
獲取構(gòu)造器
Student student = new Student();
Class<? extends Student> clazz3 = student.getClass();
System.out.println("student.getClass(): " + clazz3.getName());

//獲取所有的構(gòu)造器
Constructor<?>[] constructors = clazz3.getDeclaredConstructors();
System.out.print("get all Constructors");
for (Constructor<?> constructor : constructors) {
    Class<?>[] parameterTypes = constructor.getParameterTypes();
    System.out.print("parameters length: " + parameterTypes.length);
    System.out.print(" constructor Modifier: " + Modifier.toString(constructor.getModifiers()));
    for (Class<?> clazz : parameterTypes) {
        System.out.print(" " + clazz.getName());
    }
    System.out.print("\n");
}

//獲取public的構(gòu)造器
constructors = clazz3.getConstructors();
System.out.print("get public Constructors");
for (Constructor<?> constructor : constructors) {
    Class<?>[] parameterTypes = constructor.getParameterTypes();
    System.out.print("parameters length: " + parameterTypes.length);
    System.out.print(" constructor Modifier: " + Modifier.toString(constructor.getModifiers()));
    for (Class<?> clazz : parameterTypes) {
        System.out.print(" " + clazz.getName());
    }
    System.out.print("\n");
}

//獲取指定參數(shù)的構(gòu)造器
Class<?>[] parameters = {int.class};
Constructor<?> constructor;
try {
    System.out.print("get public Constructors");
    constructor = clazz3.getDeclaredConstructor(parameters);
    System.out.println("constructor Modifier: " + Modifier.toString(constructor.getModifiers()));
    constructor.setAccessible(true);
    constructor.newInstance(11);
} catch (Exception e) {
    e.printStackTrace();
}

執(zhí)行結(jié)果:

get all Constructors
parameters length: 2 constructor Modifier: public java.lang.String int
parameters length: 1 constructor Modifier: private java.lang.String
parameters length: 1 constructor Modifier: private int
parameters length: 0 constructor Modifier: public

get public Constructors
parameters length: 2 constructor Modifier: public java.lang.String int
parameters length: 0 constructor Modifier: public

get public Constructors
constructor Modifier: private
Constructor age!

反射字段
Student student = new Student("大白", 1);
Class<? extends Student> clazz3 = student.getClass();

Field[] fields = clazz3.getDeclaredFields();
System.out.print("fields length: " + fields.length);
for (Field field : fields) {
    System.out.print("field Modifier: " + Modifier.toString(field.getModifiers()));
    System.out.print(" " + field.getName());
}

fields = clazz3.getFields();
System.out.print("fields length: " + fields.length);
for (Field field : fields) {
    System.out.print("field Modifier: " + Modifier.toString(field.getModifiers()));
    System.out.print(" " + field.getName());
}

try {
    Field field = clazz3.getDeclaredField("FINAL_FILED");
    System.out.println("fields FINAL_FILED value: " + field.get(null));

    field = clazz3.getDeclaredField("name");
    field.setAccessible(true);
    System.out.println("fields name value: " + field.get(student));
    field.set(student, "小白");
    System.out.println("fields name value: " + field.get(student));
} catch (Exception e) {
    e.printStackTrace();
}

執(zhí)行結(jié)果:
fields length: 4
field Modifier: public static staticFiled
field Modifier: public static final FINAL_FILED
field Modifier: private name
field Modifier: public age

fields length: 3
field Modifier: public static staticFiled
field Modifier: public static final FINAL_FILED
field Modifier: public age

fields FINAL_FILED value: 100
fields name value: 大白
fields name value: 小白
Constructor name & age!

這里使用了反射修改了name字段的值痢畜,并使用field.setAccessible(true);修改了name字段的訪問(wèn)權(quán)限

反射方法
Student student = new Student("大白", 1);
Class<? extends Student> clazz3 = student.getClass();

System.out.println("get all methods");
Method[] methods = clazz3.getDeclaredMethods();
System.out.println("methods length: " + methods.length);
for (Method method : methods) {
    Class<?>[] parameterTypes = method.getParameterTypes();
    System.out.print("method name: " + method.getName());
    System.out.print(" method Modifier: " + Modifier.toString(method.getModifiers()));
    System.out.print(" parameters length: " + parameterTypes.length);
    for (Class<?> clazz : parameterTypes) {
        System.out.print(" " + clazz.getName());
    }
}

methods = clazz3.getMethods();
System.out.println("methods length: " + methods.length);
for (Method method : methods) {
    Class<?>[] parameterTypes = method.getParameterTypes();
    System.out.print("method name: " + method.getName());
    System.out.print(" method Modifier: " + Modifier.toString(method.getModifiers()));
    System.out.print(" parameters length: " + parameterTypes.length);
    for (Class<?> clazz : parameterTypes) {
        System.out.print(" " + clazz.getName());
    }
}

try {
    Class<?>[] parameters = {int.class};
    Method method = clazz3.getDeclaredMethod("setAge", parameters);
    method.setAccessible(true);
    System.out.println("fields age value: " + student.age);
    method.invoke(student, 20);
    System.out.println("fields age value: " + student.age);
} catch (Exception e) {
    e.printStackTrace();
}

try {
    Method method = clazz3.getDeclaredMethod("staticMethod");
    method.setAccessible(true);
    method.invoke(null);
} catch (Exception e) {
    e.printStackTrace();
}

執(zhí)行結(jié)果:

get all methods
methods length: 5

method name: getName method Modifier: public parameters length: 0
method name: setName method Modifier: public parameters length: 1 java.lang.String
method name: staticMethod method Modifier: public static parameters length: 0
method name: getAge method Modifier: private parameters length: 0
method name: setAge method Modifier: private parameters length: 1 int

methods length: 12

method name: getName method Modifier: public parameters length: 0
method name: setName method Modifier: public parameters length: 1 java.lang.String
method name: staticMethod method Modifier: public static parameters length: 0
method name: wait method Modifier: public final native parameters length: 1 long
method name: wait method Modifier: public final parameters length: 2 long int
method name: wait method Modifier: public final parameters length: 0
method name: equals method Modifier: public parameters length: 1 java.lang.Object
method name: toString method Modifier: public parameters length: 0
method name: hashCode method Modifier: public native parameters length: 0
method name: getClass method Modifier: public final native parameters length: 0
method name: notify method Modifier: public final native parameters length: 0
method name: notifyAll method Modifier: public final native parameters length: 0

fields age value: 1
invoke private Method!
fields age value: 20

invoke static Method!

這里需要注意的是clazz3.getMethods返回的長(zhǎng)度是12,包括父類Object中的public方法

反射注解
Student student = new Student();
Class<? extends Student> clazz3 = student.getClass();
Annotation[] annotations = clazz3.getDeclaredAnnotations();
System.out.println("annotations length: " + annotations.length);
for (Annotation annotation : annotations) {
    if (annotation instanceof ClassAnnotation) {
        System.out.println("annotations name: " + ((ClassAnnotation) annotation).value());
    }
    Class<? extends Annotation> clazz = annotation.annotationType();
    System.out.print("annotations Modifier: " + Modifier.toString(clazz.getModifiers()));
}

//獲取指定參數(shù)的構(gòu)造器
Class<?>[] parameters = {};
try {
    Constructor<?> constructor = clazz3.getDeclaredConstructor(parameters);
    annotations = constructor.getDeclaredAnnotations();
    System.out.println("annotations length: " + annotations.length);
    for (Annotation annotation : annotations) {
        if (annotation instanceof ConstructorAnnotation) {
            System.out.println("annotations name: " + ((ConstructorAnnotation) annotation).value());
        }
        Class<? extends Annotation> clazz = annotation.annotationType();
        System.out.print("annotations Modifier: " + Modifier.toString(clazz.getModifiers()));
    }
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

執(zhí)行結(jié)果:

annotations length: 1
annotations name: 20
annotations Modifier: public abstract interface

annotations length: 1
annotations name: 40
annotations Modifier: public abstract interface

這里補(bǔ)上自定義注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ClassAnnotation {
    int value() default 1;
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface ConstructorAnnotation {
    int value() default 1;
}

其他注解的使用和上面類似,這里就不做分享了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末投储,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌扔罪,老刑警劉巖秉沼,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異矿酵,居然都是意外死亡唬复,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門全肮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)敞咧,“玉大人,你說(shuō)我怎么就攤上這事辜腺⌒萁ǎ” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵评疗,是天一觀的道長(zhǎng)测砂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)百匆,這世上最難降的妖魔是什么砌些? 我笑而不...
    開(kāi)封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮加匈,結(jié)果婚禮上存璃,老公的妹妹穿的比我還像新娘。我一直安慰自己雕拼,他們只是感情好纵东,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著啥寇,像睡著了一般篮迎。 火紅的嫁衣襯著肌膚如雪男图。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天甜橱,我揣著相機(jī)與錄音逊笆,去河邊找鬼。 笑死岂傲,一個(gè)胖子當(dāng)著我的面吹牛难裆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镊掖,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼乃戈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了亩进?” 一聲冷哼從身側(cè)響起症虑,我...
    開(kāi)封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎归薛,沒(méi)想到半個(gè)月后谍憔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡主籍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年习贫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片千元。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡苫昌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幸海,到底是詐尸還是另有隱情祟身,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布物独,位于F島的核電站月而,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏议纯。R本人自食惡果不足惜父款,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瞻凤。 院中可真熱鬧憨攒,春花似錦、人聲如沸阀参。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蛛壳。三九已至杏瞻,卻和暖如春所刀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捞挥。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工浮创, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人砌函。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓斩披,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親讹俊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子垦沉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 什么是反射 反射是一個(gè)很牛的功能,能夠在程序運(yùn)行時(shí)修改程序的行為仍劈。但是反射是非常規(guī)手段厕倍,反射有風(fēng)險(xiǎn),應(yīng)用需謹(jǐn)慎贩疙。把...
    dashingqi閱讀 610評(píng)論 0 1
  • 深入理解Java注解 依賴注入是一種較流行的設(shè)計(jì)模式讹弯,在 Android開(kāi)發(fā)中也有很多實(shí)用的依賴注入框架,可以幫助...
    niuniu_it閱讀 290評(píng)論 0 1
  • 對(duì)象的創(chuàng)建與銷毀 Item 1: 使用static工廠方法屋群,而不是構(gòu)造函數(shù)創(chuàng)建對(duì)象:僅僅是創(chuàng)建對(duì)象的方法,并非Fa...
    孫小磊閱讀 1,981評(píng)論 0 3
  • 自己備忘,隨便寫 android網(wǎng)絡(luò)框架源碼解析及對(duì)比 android常用網(wǎng)絡(luò)框架對(duì)比 Volley: 特點(diǎn) 基于...
    幻海流心閱讀 1,455評(píng)論 0 4
  • 官方文檔 The Apache Groovy programming language Groovy Langua...
    LeonXtp閱讀 526評(píng)論 0 0