Java之反射筆記

  • 概念
    JAVA反射機(jī)制是在運行狀態(tài)中养叛,對于任意一個類翠忠,都能夠知道這個類的所有屬性和方法;對于任意一個對象盗温,都能夠調(diào)用它的任意一個方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機(jī)制成肘。
    要想解剖一個類,必須先要獲取到該類的字節(jié)碼文件對象卖局。而解剖使用的就是Class類中的方法。所以先要獲取到每一個字節(jié)碼文件對應(yīng)的Class類型的對象艇劫。

  • 類加載過程


    image.png

    Class類的實例表示正在運行的Java應(yīng)用程序中的類和接口吼驶。每個類只會產(chǎn)生一個Class對象惩激,在類加載的時候自動創(chuàng)建。

  • 獲取class方式

public class ClassTest {
    public static void main(String[] args) {

        try {
            // 通過Class.forName獲取
            Class<?> aClass = Class.forName("clas.User");
            System.out.println(aClass.getSimpleName());
            System.out.println("---------------");
            // 通過類明.class獲取
            Class<User> userClass = User.class;
            System.out.println(userClass.getSimpleName());
            System.out.println("---------------");
            // 通過對象getClass()獲取
            Class<? extends User> aClass1 = new User().getClass();
            System.out.println(aClass1.getSimpleName());

             // 如果是基本類型 可以通過TYPE獲取
            Class<Integer> integerClass = Integer.class;
            Class<Integer> type = Integer.TYPE;
            System.out.println(integerClass.getSimpleName());
            System.out.println(type.getSimpleName());

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}
  • Class 部分方法使用
    父類Person
public class Person {
    public String name;
    private String age;

    public void say1(String a){
        System.out.println("is person say1"+a);
    }

    private void say2(){
        System.out.println("is person say2");
    }
}

子類User

public class User extends Person{

    public String className;

    private String teachName;

    public User() {

    }
    private User(String className) {
        this.className = className;
    }

    public User(String className, String teachName) {
        this.className = className;
        this.teachName = teachName;
    }

    public void read1(String a){
        System.out.println("is user read1"+a);
    }
    private void read2(String a){
        System.out.println("is user read2"+a);
    }

    public String getTeachName() {
        return teachName;
    }

    public void setTeachName(String teachName) {
        this.teachName = teachName;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    @Override
    public String toString() {
        return "User{" +
                "className='" + className + '\'' +
                ", teachName='" + teachName + '\'' +
                '}';
    }
}

需要注意上面兩個類的屬性和方法的訪問修飾符

測試類

public class ClassApi {
    public static void main(String[] args) {
        try {
            Class<?> clazz = Class.forName("clas.User");

            // 獲取成員變量,包含子類和父類蟹演,只能是public修飾的屬性
            Field[] fields = clazz.getFields();
            System.out.println("*****獲取成員變量,包含子類和父類风钻,只能是public修飾的屬性******");
            for (Field field : fields) {
                System.out.println(field);
                System.out.println("------------");


            }
            System.out.println("*****返回當(dāng)前類的所有屬性*******");
            //返回當(dāng)前類的所有屬性,與訪問修飾符無關(guān)酒请。排除父類骡技。
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println(declaredField);
                System.out.println("--------");
            }
            System.out.println("*****訪問私有屬性*******");
            // 訪問私有屬性
            Field teachName = clazz.getDeclaredField("teachName");// 這是一個私有屬性
            teachName.setAccessible(true);//破壞封裝性
            User o = (User) clazz.newInstance();
            teachName.set(o,"張三");
            System.out.println(o.getTeachName());

            // 獲取普通方法,當(dāng)前對象以及父類對象的所有公共方法
            Method[] methods = clazz.getMethods();
            System.out.println("*****獲取普通方法,當(dāng)前對象以及父類對象的所有公共方法*******");
            for (Method method : methods) {
                System.out.println(method);
                System.out.println("--------");

            }
            //獲取當(dāng)前類的所有方法羞反,與修飾詞無關(guān)
            Method[] declaredMethods = clazz.getDeclaredMethods();
            System.out.println("*****獲取當(dāng)前類的所有方法翎嫡,與修飾詞無關(guān)*******");
            for (Method declaredMethod : declaredMethods) {
                System.out.println(declaredMethod);
                System.out.println("--------");
            }

            // 訪問當(dāng)前類私有方法
            System.out.println("*****訪問當(dāng)前類私有方法*******");
            Method read1 = clazz.getDeclaredMethod("read1", String.class);
            read1.invoke(o,"讀英語");
            Method read2 = clazz.getDeclaredMethod("read2", String.class);//這是一個私有方法
            read2.setAccessible(true);//沒有設(shè)置該屬性會報IllegalAccessException
            read2.invoke(o,"讀語文");

            // 無法獲取父類的方法噢 NoSuchMethodException
            //Method say1 = clazz.getDeclaredMethod("say1", String.class);
            //如何獲取父類的私有屬性呢?
            //先得到父類class
            System.out.println("*****獲取父類的私有屬性和方法*******");
            Class<?> superclass = clazz.getSuperclass();
            Field[] declaredFields1 = superclass.getDeclaredFields();
            Method[] declaredMethods1 = superclass.getDeclaredMethods();
            for (Field field : declaredFields1) {
                System.out.println(field);
            }
            System.out.println("----方法----");
            for (Method method : declaredMethods1) {
                System.out.println(method);
            }

            // 獲取構(gòu)造方法 ,不能訪問父類構(gòu)造方法猴鲫,構(gòu)造方法不會繼承
            System.out.println("*****獲取構(gòu)造方法敷燎,公有的*******");
            Constructor<?>[] constructors = clazz.getConstructors();
            for (Constructor<?> constructor : constructors) {
                System.out.println(constructor);
            }
            System.out.println("----獲取構(gòu)造方法,公有的與私有的----");
            Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
            for (Constructor<?> declaredConstructor : declaredConstructors) {
                System.out.println(declaredConstructor);
            }
            // 訪問私有構(gòu)造方法
            System.out.println("----訪問私有構(gòu)造方法----");
            Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String.class);//私有的
            declaredConstructor.setAccessible(true);
            User obj = (User) declaredConstructor.newInstance("李四");
            System.out.println(obj);

        } catch (ClassNotFoundException | NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}

打印結(jié)果

*****獲取成員變量,包含子類和父類澄惊,只能是public修飾的屬性******
public java.lang.String clas.User.className
------------
public java.lang.String clas.Person.name
------------
*****返回當(dāng)前類的所有屬性*******
public java.lang.String clas.User.className
--------
private java.lang.String clas.User.teachName
--------
*****訪問私有屬性*******
張三
*****獲取普通方法唆途,當(dāng)前對象以及父類對象的所有公共方法*******
public java.lang.String clas.User.toString()
--------
public java.lang.String clas.User.getClassName()
--------
public void clas.User.read1(java.lang.String)
--------
public java.lang.String clas.User.getTeachName()
--------
public void clas.User.setClassName(java.lang.String)
--------
public void clas.User.setTeachName(java.lang.String)
--------
public void clas.Person.say1(java.lang.String)
--------
public final void java.lang.Object.wait() throws java.lang.InterruptedException
--------
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
--------
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
--------
public boolean java.lang.Object.equals(java.lang.Object)
--------
public native int java.lang.Object.hashCode()
--------
public final native java.lang.Class java.lang.Object.getClass()
--------
public final native void java.lang.Object.notify()
--------
public final native void java.lang.Object.notifyAll()
--------
*****獲取當(dāng)前類的所有方法,與修飾詞無關(guān)*******
public java.lang.String clas.User.toString()
--------
public java.lang.String clas.User.getClassName()
--------
public void clas.User.read1(java.lang.String)
--------
private void clas.User.read2(java.lang.String)
--------
public java.lang.String clas.User.getTeachName()
--------
public void clas.User.setClassName(java.lang.String)
--------
public void clas.User.setTeachName(java.lang.String)
--------
*****訪問當(dāng)前類私有方法*******
is user read1讀英語
is user read2讀語文
*****獲取父類的私有屬性和方法*******
public java.lang.String clas.Person.name
private java.lang.String clas.Person.age
----方法----
public void clas.Person.say1(java.lang.String)
private void clas.Person.say2()
*****獲取構(gòu)造方法掸驱,公有的*******
public clas.User(java.lang.String,java.lang.String)
public clas.User()
----獲取構(gòu)造方法肛搬,公有的與私有的----
public clas.User(java.lang.String,java.lang.String)
private clas.User(java.lang.String)
public clas.User()
----訪問私有構(gòu)造方法----
User{className='李四', teachName='null'}

Process finished with exit code 0

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市毕贼,隨后出現(xiàn)的幾起案子温赔,更是在濱河造成了極大的恐慌,老刑警劉巖鬼癣,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陶贼,死亡現(xiàn)場離奇詭異,居然都是意外死亡扣溺,警方通過查閱死者的電腦和手機(jī)骇窍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锥余,“玉大人腹纳,你說我怎么就攤上這事∏蹋” “怎么了嘲恍?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長雄驹。 經(jīng)常有香客問我佃牛,道長,這世上最難降的妖魔是什么医舆? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任俘侠,我火速辦了婚禮象缀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘爷速。我一直安慰自己央星,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布惫东。 她就那樣靜靜地躺著莉给,像睡著了一般。 火紅的嫁衣襯著肌膚如雪廉沮。 梳的紋絲不亂的頭發(fā)上颓遏,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機(jī)與錄音滞时,去河邊找鬼叁幢。 笑死,一個胖子當(dāng)著我的面吹牛漂洋,可吹牛的內(nèi)容都是我干的遥皂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼刽漂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了弟孟?” 一聲冷哼從身側(cè)響起贝咙,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拂募,沒想到半個月后庭猩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡陈症,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年蔼水,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片录肯。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡趴腋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出论咏,到底是詐尸還是另有隱情优炬,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布厅贪,位于F島的核電站蠢护,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏养涮。R本人自食惡果不足惜葵硕,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一眉抬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧懈凹,春花似錦吐辙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至威沫,卻和暖如春贤惯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棒掠。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工孵构, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烟很。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓颈墅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親雾袱。 傳聞我的和親對象是個殘疾皇子恤筛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355