Java反射筆記

Java反射的概述

什么是Java的反射機(jī)制

Java反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為Java語言的反射機(jī)制。

Java的反射機(jī)制的作用

Java反射機(jī)制的主要作用是用來編寫一些通用性比較高的代碼或者框架

反射常用對(duì)象的概述

  • Class
    Class類的實(shí)例表示正在運(yùn)行的Java應(yīng)用程序中的類與接口
  • Constructor
    關(guān)于類的單個(gè)構(gòu)造方法的信息以及對(duì)它的訪問權(quán)限
  • Field
    Field提供有關(guān)類或接口的單個(gè)字段的信息,以及對(duì)它動(dòng)態(tài)訪問權(quán)限
  • Method
    Method 提供關(guān)于類或接口上單獨(dú)某個(gè)方法的信息

示意圖如下:



如,上圖示例程序中的Person.java在經(jīng)過編譯后變?yōu)?class文件,由ClassLoader加載到JVM的內(nèi)存中。原本的類中對(duì)應(yīng)的構(gòu)造方法,字段,方法等都會(huì)變?yōu)橄鄳?yīng)的Constructor對(duì)象,F(xiàn)ield對(duì)象,Method對(duì)象等

反射的API

Class 類

Java中的java.lang.Class類用于表示一個(gè)類的字節(jié)碼(.class)文件
如何獲得一個(gè)class文件對(duì)應(yīng)的Class對(duì)象呢?有三種方法:

  1. 類名.class
  2. 對(duì)象.getClass()
    這種方式需要獲得具體的對(duì)象,并使用父類的Object.getClass()方法獲取
  3. Class.forName("包名.類名")
    forName方法用于加載類字節(jié)碼到內(nèi)存中,并封裝成一個(gè)Class對(duì)象

對(duì)于這三種獲取方式,可以看示例:
現(xiàn)有Person類:

package classTest;

public class Person {
    private String name;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Person(){

    }

    public Person(String name,String sex){
        this.name = name;
        this.sex = sex;
    }

    public void sayHello(){
        System.out.println("hello !");
    }
}

    @Test
    public void test1(){
        // 1 類名.class
        Class clazzPerson1 = Person.class;

        // 2 對(duì)象.getClass()
        Person p = new Person();
        Class clazzPerson2 = p.getClass();

        // 3 Class.forName()
        try {
            Class clazzPerson3 = Class.forName("classTest.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

Constructor 類

  • Constructor類的實(shí)例對(duì)象代表類的一個(gè)構(gòu)造方法
  • 得到某個(gè)類所有的構(gòu)造方法
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
  • 得到指定的構(gòu)造方法并調(diào)用
Constructor constructor = Class.forName("java.lang.String").getConstructor(String.class);
String str = (String)constructor.newInstance("abc");
  • Class類的newInstance() 方法用來調(diào)用類的默認(rèn)構(gòu)造方法
String obj = (String)Class.forName("java.lang.String").newInstance();

測試用例如下:

    @Test
    public void test2() throws Exception {
        // 獲得無參的構(gòu)造方法
        Class clazz = Class.forName("classTest.Person");
        Constructor constructor = clazz.getConstructor();
        Person p = (Person)constructor.newInstance();
        p.sayHello();

        // 獲得有參的構(gòu)造方法
        Constructor constructor2 = clazz.getConstructor(String.class,String.class);
        Person p2 = (Person)constructor2.newInstance("張三","男");
        p2.sayHello();
        System.out.println(p2.getName());
        System.out.println(p2.getSex());
    }

運(yùn)行結(jié)果如下:


Field 類

  • Field類代表某個(gè)類中的一個(gè)成員變量,并提供動(dòng)態(tài)的訪問權(quán)限
  • Filed對(duì)象的獲取
    • 得到所有的成員變量
    Field[] fields = clazz.getFields(); // 獲取所有public屬性
    Field[] fields = clazz.getDeclaredFields(); // 取得所有聲明的屬性
    
    • 得到指定的成員變量
    Field name = clazz.getField("name");
    Field name = clazz.getDeclaredField("name");  
    
  • 設(shè)置Field變量是否可以訪問
field.setAccessible(boolean);
  • Field變量值的讀取,設(shè)置
field.get(obj);
field.set(obj,value);

測試用例:
首先將Person類的name屬性變?yōu)楣校?/p>

package classTest;

public class Person {
    public String name;
    private String sex;

    public Person(){

    }

    public Person(String name,String sex){
        this.name = name;
        this.sex = sex;
    }

    public void sayHello(){
        System.out.println("hello !");
    }
}

我們可以用Field對(duì)象來操作獲取字段,獲取字段值并設(shè)置字段值:

    @Test
    public void test3() throws Exception {
        // 測試公有屬性
        Class clazz = Class.forName("classTest.Person");
        Person person = (Person) clazz.getConstructor().newInstance();
        Field fieldName = clazz.getField("name");
        fieldName.set(person,"李四");
        System.out.println(fieldName.get(person));


        // 測試私有屬性
        Person person2 = (Person) clazz.getConstructor().newInstance();
        Field fieldSex = clazz.getDeclaredField("sex");
        fieldSex.setAccessible(true);
        fieldSex.set(person2,"女");
        System.out.println(fieldSex.get(person2));
    }

顯示結(jié)果為:


Method 類

  • Method 類代表某個(gè)類中的一個(gè)成員方法
  • Method 對(duì)象的獲得
    • 獲得所有方法
    getDeclaredMethods()
    getMethods()
    
    • 獲得指定的方法
     //name為方法名稱
    getDeclredMethods(String name,Class<?>...parameterTypes)
    getMethods(String name,Class<?>...parameterTypes)
    
  • 通過反射執(zhí)行方法
invoke(Object obj,Object...args)

測試程序:
首先對(duì)Person類改動(dòng)如下:

package classTest;

public class Person {
    public String name;
    private String sex;

    public Person(){

    }

    public Person(String name,String sex){
        this.name = name;
        this.sex = sex;
    }

    public void sayHello(){
        System.out.println("hello !");
    }

    // 私有方法
    private void run(){
        System.out.println("run !");
    }
    // 私有帶參方法
    private void eat(String foodName){
        System.out.println("eat " + foodName + " !");
    }
}

Method類可以對(duì)象可以獲取并操作屬于一個(gè)類的所有方法

    @Test
    public void test4() throws Exception {
        // 測試共有方法
        Class clazz = Class.forName("classTest.Person");
        Person person = (Person) clazz.getConstructor().newInstance();
        Method method = clazz.getMethod("sayHello");
        method.invoke(person);

        // 測試私有方法
        Method method2 = clazz.getDeclaredMethod("run");
        method2.setAccessible(true);
        method2.invoke(person);

        // 測試私有帶參的方法
        Method method3 = clazz.getDeclaredMethod("eat", String.class);
        method3.setAccessible(true);
        method3.invoke(person,"apple");
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 課程地址:Java基礎(chǔ)之 — 反射(非常重要) (使用的前提條件:必須先得到代表的字節(jié)碼的Class,Cla...
    叨唧唧的閱讀 759評(píng)論 0 2
  • 1.在C/C++中實(shí)現(xiàn)本地方法 生成C/C++頭文件之后,你就需要寫頭文件對(duì)應(yīng)的本地方法。注意:所有的本地方法的第...
    JayQiu閱讀 2,532評(píng)論 0 3
  • Jni數(shù)據(jù)類型 Jni方法 來自 http://blog.chinaunix.net/uid-22028680-i...
    FlyDragonInSky閱讀 1,006評(píng)論 0 0
  • 2017年12月1日 10:52:57 Java的反射機(jī)制它知道類的基本結(jié)構(gòu),這種對(duì)Java類結(jié)構(gòu)探知的能力,我們...
    silencefun閱讀 183評(píng)論 0 0
  • 小區(qū)健身器材區(qū)。“喂,你相信嗎,我能感覺到,自己被注視著?!卑⒈蟠髦鷻C(jī),在橢圓機(jī)上慢慢踩著。他說出這句話的時(shí)候,...
    遠(yuǎn)航員阿花閱讀 360評(píng)論 0 0

友情鏈接更多精彩內(nèi)容