溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java中的反射指的是什么

發(fā)布時(shí)間:2021-07-19 10:41:23 來(lái)源:億速云 閱讀:160 作者:chen 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“Java中的反射指的是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Java中的反射指的是什么”吧!

目錄
  • 到底什么是反射呢???

  • 2. 類的生命周期

  • 3. Java反射框架主要提供以下功能:

  • 反射的基本用法

    • 1. 獲得Class對(duì)象

    • 2. 判斷是否為某個(gè)類的實(shí)類

    • 3.創(chuàng)建實(shí)例

    • 4. 獲取構(gòu)造器信息

    • 5. 獲取方法

    • 6. 獲取類的成員變量(字段)信息

    • 7. 利用反射創(chuàng)建數(shù)組

    • 反射的注意事項(xiàng)

    • 反射的主要用途

  • 總結(jié)

    到底什么是反射呢???

    反射的核心就是JVM在運(yùn)行時(shí)才動(dòng)態(tài)加載類或調(diào)用方法,訪問(wèn)屬性,它不需要事先(寫(xiě)代碼的時(shí)候或編譯期)知道運(yùn)行對(duì)象是誰(shuí)。

    每一個(gè)類都會(huì)產(chǎn)生一個(gè)對(duì)應(yīng)的Class對(duì)象,也就是保存在.class文件。

    所有類都是在對(duì)其第一次使用時(shí),動(dòng)態(tài)加載到JVM的,當(dāng)程序創(chuàng)建一個(gè)對(duì)類的靜態(tài)成員的引用時(shí),就會(huì)加載這個(gè)類,Class對(duì)象僅在需要的時(shí)候才會(huì)加載,static初始化是在類加載時(shí)進(jìn)行的。

    public class TestMain {
        public static void main(String[] args) {
            System.out.println(Test.name); // 對(duì)Test類的靜態(tài)成員name引用。
        }
    }
    class Test {
        public static String name = "Test Name";
        static {
            System.out.println("Test靜態(tài)塊");
        }
        public Test() {
            System.out.println("Test構(gòu)造了");
        }
    }

    輸出:

    Test靜態(tài)塊 Test Name

    2. 類的生命周期

    一個(gè)類編譯完成后,下一步就是開(kāi)始使用類,怎么使用?

    類編譯完成后,開(kāi)始使用類,在程序執(zhí)行中JVM通過(guò)裝載,鏈接,初始化這3個(gè)步驟完成。

    1.裝載:由類加載器完成,找到對(duì)應(yīng)的字節(jié)碼,創(chuàng)建一個(gè)Class對(duì)象。

    類加載器首先會(huì)檢查這個(gè)類的Class對(duì)象是否已經(jīng)被加載過(guò),如果沒(méi)有加載,默認(rèn)的類加載器就會(huì)根據(jù)類名查找對(duì)應(yīng)的.class文件。

    加載器將.class文件的二進(jìn)制文件裝入JVM的方法區(qū),并且在堆區(qū)創(chuàng)建描述這個(gè)類的java.lang.Class對(duì)象,用來(lái)封裝數(shù)據(jù),但是同一個(gè)類只會(huì)被類裝載器裝載一次。

    2.鏈接:就是把二進(jìn)制數(shù)據(jù)組裝為可以運(yùn)行的狀態(tài)

    校驗(yàn):一般用來(lái)確認(rèn)此二進(jìn)制文件是否適合當(dāng)前的JVM(版本)

    準(zhǔn)備:為靜態(tài)成員分配內(nèi)存空間,并設(shè)置默認(rèn)值。

    解析:轉(zhuǎn)換常量池中的代碼作為直接引用的過(guò)程,直到所有的符號(hào)都可以被運(yùn)行程序使用(建立完整的對(duì)應(yīng)關(guān)系)驗(yàn)證類中的字節(jié)碼,為靜態(tài)域分配空間。

    3.初始化:如果該類有父類,則對(duì)其初始化,執(zhí)行靜態(tài)初始化器和靜態(tài)初始化塊。

    3. Java反射框架主要提供以下功能:

    在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象

    在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法

    在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類

    在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法(通過(guò)反射甚至可以調(diào)用private方法)

    反射的基本用法

    1. 獲得Class對(duì)象

    <1> 使用Class類的forName靜態(tài)方法:

    public static Class<?> forName(String className) 
    在JDBC開(kāi)發(fā)中常用此方法加載數(shù)據(jù)庫(kù)驅(qū)動(dòng): Class.forName(driver);
    //加入Java開(kāi)發(fā)交流君樣:756584822一起吹水聊天

    <2> 直接獲取某一個(gè)對(duì)象的class:(編譯時(shí)已知類型名稱或已知對(duì)象)

    Class<?> klass = int.class;
    Class<?> classInt = Integer.TYPE;

    <3> 調(diào)用某個(gè)對(duì)象的getClass()方法:

    StringBuilder str = new StringBuilder("123");
    Class<?> klass = str.getClass();

    注意: 使用.class來(lái)創(chuàng)建Class對(duì)象的引用時(shí),不會(huì)自動(dòng)初始化該Class對(duì)象,使用forName(…)會(huì)自動(dòng)初始化該Class對(duì)象。

    2. 判斷是否為某個(gè)類的實(shí)類

    一般:用instanceof關(guān)鍵字判斷

    反射:反射中Class對(duì)象的isInstance()方法

    public native boolean isInstance(Object obj);

    3.創(chuàng)建實(shí)例

    通過(guò)反射來(lái)生成對(duì)象主要有兩種方式:

    <1> 使用Class對(duì)象的newInstance()方法來(lái)創(chuàng)建Class對(duì)象對(duì)應(yīng)類的實(shí)例。

    Class<?> c = String.class;
    Object str = c.newInstance();

    <2> 先通過(guò)Class對(duì)象獲取指定的Constructor對(duì)象,再調(diào)用Constructor對(duì)象的newInstance()方法來(lái)創(chuàng)建實(shí)例。

    // 獲取String所對(duì)應(yīng)的Class對(duì)象
    Class<?> c = String.class;
    // 獲取String類帶一個(gè)String參數(shù)的構(gòu)造器
    Constructor constructor = c.getConstructor(String.class);
    // 根據(jù)構(gòu)造器創(chuàng)建實(shí)例
    Object obj = constructor.newInstance("23333");
    System.out.println(obj);

    4. 獲取構(gòu)造器信息

    主要是通過(guò)Class類的getConstructor方法得到Constructor類的一個(gè)實(shí)例,而Constructor類有一個(gè)newInstance方法可以創(chuàng)建一個(gè)對(duì)象實(shí)例

    5. 獲取方法

    <1> getDeclaredMethods() – 返回類或接口聲明的所有方法,包括公共、保護(hù)、默認(rèn)(包)訪問(wèn)和私有方法,但不包括繼承的方法

    public Method[] getDeclaredMethods() throws SecurityException

    <2> getMethods() – 返回某個(gè)類的所有公共(public)方法,包括繼承的公有方法

    public Method[] getMethods() throws SecurityException

    <3> getDeclaredMethod() – 返回一個(gè)特定的方法,其中第一個(gè)參數(shù)為方法名稱,后面的參數(shù)為方法的參數(shù)類型對(duì)應(yīng)的Class對(duì)象

    public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

    <4> getMethod() – 返回一個(gè)特定的方法,其中第一個(gè)參數(shù)為方法名稱,后面的參數(shù)為方法的參數(shù)類型對(duì)應(yīng)的Class對(duì)象

    public Method getMethod(String name, Class<?>... parameterTypes)

    6. 獲取類的成員變量(字段)信息

    getDeclaredFields() – 訪問(wèn)所有已聲明的成員變量,但不能訪問(wèn)繼承的成員變量。

    getFileds() – 訪問(wèn)所有已聲明的公有(public)成員變量,包括繼承的公有成員變量。

    getDeclaredField() – 特定訪問(wèn)所有成員變量(不包括繼承的),參數(shù)為成員變量的名字。

    getFiled() – 特定訪問(wèn)公有成員變量(包括繼承的),參數(shù)為成員變量的名字。

    7. 利用反射創(chuàng)建數(shù)組

    Class<?> cls = Class.forName("java.lang.String");
    Object array = Array.newInstance(cls, 25);
    //往數(shù)組里添加內(nèi)容
    Array.set(array, 0, "hello");
    Array.set(array, 1, "Java");
    Array.set(array, 2, "fuck");
    Array.set(array, 3, "Scala");
    Array.set(array, 4, "Clojure");
    //獲取某一項(xiàng)的內(nèi)容
    System.out.println(Array.get(array,3));
    //加入Java開(kāi)發(fā)交流君樣:756584822一起吹水聊天

    其中的Array類為java.lang.reflect.Array類,我們通過(guò)Array.newInstance()創(chuàng)建數(shù)組對(duì)象,它的原型是:

    public static Object newInstance(Class<?> componentType, int length) throws NegativeArraySizeException {
    return newArray(componentType, length);
    }

    newArray()方法是一個(gè)Native方法:

    private static native Object newArray(Class<?> componentType, int length) throws NegativeArraySizeException;

    反射的注意事項(xiàng)

    由于反射會(huì)額外消耗一定的系統(tǒng)資源,因此如果不需要?jiǎng)討B(tài)地創(chuàng)建一個(gè)對(duì)象,那么就不需要用反射。反射調(diào)用方法時(shí)可以忽略權(quán)限檢查,因此可能會(huì)破壞封裝性而導(dǎo)致安全問(wèn)題。

    反射的主要用途

    最重要的用途就是開(kāi)發(fā)各種通用框架

    很多框架(比如Spring)都是配置化的(比如通過(guò)XML文件配置JavaBean,Action之類的),為了保證框架的通用性,它們可能需要根據(jù)配置文件加載不同的對(duì)象或類,調(diào)用不同的方法,這個(gè)時(shí)候就必須用到反射——運(yùn)行時(shí)動(dòng)態(tài)加載需要加載的對(duì)象。

    到此,相信大家對(duì)“Java中的反射指的是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI