溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中的反射指的是什么

發布時間:2021-07-19 10:41:23 來源:億速云 閱讀:194 作者:chen 欄目:開發技術

本篇內容主要講解“Java中的反射指的是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java中的反射指的是什么”吧!

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

  • 2. 類的生命周期

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

  • 反射的基本用法

    • 1. 獲得Class對象

    • 2. 判斷是否為某個類的實類

    • 3.創建實例

    • 4. 獲取構造器信息

    • 5. 獲取方法

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

    • 7. 利用反射創建數組

    • 反射的注意事項

    • 反射的主要用途

  • 總結

    到底什么是反射呢???

    反射的核心就是JVM在運行時才動態加載類或調用方法,訪問屬性,它不需要事先(寫代碼的時候或編譯期)知道運行對象是誰。

    每一個類都會產生一個對應的Class對象,也就是保存在.class文件。

    所有類都是在對其第一次使用時,動態加載到JVM的,當程序創建一個對類的靜態成員的引用時,就會加載這個類,Class對象僅在需要的時候才會加載,static初始化是在類加載時進行的。

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

    輸出:

    Test靜態塊 Test Name

    2. 類的生命周期

    一個類編譯完成后,下一步就是開始使用類,怎么使用?

    類編譯完成后,開始使用類,在程序執行中JVM通過裝載,鏈接,初始化這3個步驟完成。

    1.裝載:由類加載器完成,找到對應的字節碼,創建一個Class對象。

    類加載器首先會檢查這個類的Class對象是否已經被加載過,如果沒有加載,默認的類加載器就會根據類名查找對應的.class文件。

    加載器將.class文件的二進制文件裝入JVM的方法區,并且在堆區創建描述這個類的java.lang.Class對象,用來封裝數據,但是同一個類只會被類裝載器裝載一次。

    2.鏈接:就是把二進制數據組裝為可以運行的狀態

    校驗:一般用來確認此二進制文件是否適合當前的JVM(版本)

    準備:為靜態成員分配內存空間,并設置默認值。

    解析:轉換常量池中的代碼作為直接引用的過程,直到所有的符號都可以被運行程序使用(建立完整的對應關系)驗證類中的字節碼,為靜態域分配空間。

    3.初始化:如果該類有父類,則對其初始化,執行靜態初始化器和靜態初始化塊。

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

    在運行時構造任意一個類的對象

    在運行時調用任意一個對象的方法

    在運行時判斷任意一個對象所屬的類

    在運行時判斷任意一個類所具有的成員變量和方法(通過反射甚至可以調用private方法)

    反射的基本用法

    1. 獲得Class對象

    <1> 使用Class類的forName靜態方法:

    public static Class<?> forName(String className) 
    在JDBC開發中常用此方法加載數據庫驅動: Class.forName(driver);
    //加入Java開發交流君樣:756584822一起吹水聊天

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

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

    <3> 調用某個對象的getClass()方法:

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

    注意: 使用.class來創建Class對象的引用時,不會自動初始化該Class對象,使用forName(…)會自動初始化該Class對象。

    2. 判斷是否為某個類的實類

    一般:用instanceof關鍵字判斷

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

    public native boolean isInstance(Object obj);

    3.創建實例

    通過反射來生成對象主要有兩種方式:

    <1> 使用Class對象的newInstance()方法來創建Class對象對應類的實例。

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

    <2> 先通過Class對象獲取指定的Constructor對象,再調用Constructor對象的newInstance()方法來創建實例。

    // 獲取String所對應的Class對象
    Class<?> c = String.class;
    // 獲取String類帶一個String參數的構造器
    Constructor constructor = c.getConstructor(String.class);
    // 根據構造器創建實例
    Object obj = constructor.newInstance("23333");
    System.out.println(obj);

    4. 獲取構造器信息

    主要是通過Class類的getConstructor方法得到Constructor類的一個實例,而Constructor類有一個newInstance方法可以創建一個對象實例

    5. 獲取方法

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

    public Method[] getDeclaredMethods() throws SecurityException

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

    public Method[] getMethods() throws SecurityException

    <3> getDeclaredMethod() – 返回一個特定的方法,其中第一個參數為方法名稱,后面的參數為方法的參數類型對應的Class對象

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

    <4> getMethod() – 返回一個特定的方法,其中第一個參數為方法名稱,后面的參數為方法的參數類型對應的Class對象

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

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

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

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

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

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

    7. 利用反射創建數組

    Class<?> cls = Class.forName("java.lang.String");
    Object array = Array.newInstance(cls, 25);
    //往數組里添加內容
    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");
    //獲取某一項的內容
    System.out.println(Array.get(array,3));
    //加入Java開發交流君樣:756584822一起吹水聊天

    其中的Array類為java.lang.reflect.Array類,我們通過Array.newInstance()創建數組對象,它的原型是:

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

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

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

    反射的注意事項

    由于反射會額外消耗一定的系統資源,因此如果不需要動態地創建一個對象,那么就不需要用反射。反射調用方法時可以忽略權限檢查,因此可能會破壞封裝性而導致安全問題。

    反射的主要用途

    最重要的用途就是開發各種通用框架

    很多框架(比如Spring)都是配置化的(比如通過XML文件配置JavaBean,Action之類的),為了保證框架的通用性,它們可能需要根據配置文件加載不同的對象或類,調用不同的方法,這個時候就必須用到反射——運行時動態加載需要加載的對象。

    到此,相信大家對“Java中的反射指的是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女