亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中反射機制的使用詳解

 更新時間:2023年09月19日 08:38:03   作者:_雨_  
這篇文章主要介紹了Java中反射機制的使用詳解,Java的發(fā)射機制允許程序在運行時檢查和操作任意一個類、方法、屬性等的信息,包括了類名、方法名、屬性名、參數(shù)列表以及訪問修飾符等,需要的朋友可以參考下

反射的基本介紹

Java的發(fā)射機制(Reflection)是指在運行時動態(tài)地獲取類的信息并操作對象的能力。

Java的發(fā)射機制允許程序在運行時檢查和操作任意一個類、方法、屬性等的信息,包括了類名、方法名、屬性名、參數(shù)列表以及訪問修飾符等。

通過Java的發(fā)射機制,可以實現(xiàn)一些高級的功能,比如動態(tài)生成代理對象、動態(tài)生成類、動態(tài)配置對象等。同時,Java的一些框架也廣泛應用了發(fā)射機制,比如Spring框架中大量使用了反射機制來實現(xiàn)依賴注入和AOP等功能。

Java中一些常用的反射API包括Class、Method、Field、Constructor等。其中,Class類是反射機制的核心,通過它可以獲取一個類的所有信息。Method和Field則分別表示類中的方法和屬性,Constructor則表示類中的構(gòu)造方法。

Java的發(fā)射機制給Java編程帶來了更大的靈活性,但同時也需要注意到發(fā)射機制的運行效率相對較低,同時也可能破壞類的封裝性,因此在使用時需要謹慎考慮。

在了解反射的基本介紹之后,我們在來看看反射的需求,為什么會需要反射

先看一段代碼

代碼演示:

package com.reflection.question;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
 * 反射問題的引入
 */
@SuppressWarnings({"all"})
public class ReflectionQuestion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //根據(jù)配置文件 re.properties 指定信息, 創(chuàng)建Cat對象并調(diào)用方法hi
        //傳統(tǒng)的方式 new 對象 -》 調(diào)用方法
//        Cat cat = new Cat();
//        cat.hi(); ===> cat.cry() 修改源碼.
        //我們嘗試做一做 -> 明白反射
        //1. 使用Properties 類, 可以讀寫配置文件    Properties的底層就是HashTable
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));//加載配置文件的鍵值對到properties對象
        String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat"  根據(jù)鍵獲取值
        String methodName = properties.get("method").toString();//"hi"
        System.out.println("classfullpath=" + classfullpath);
        System.out.println("method=" + methodName);
        //2. 創(chuàng)建對象 , 傳統(tǒng)的方法,行不通 =》 反射機制
        //new classfullpath();
        //3. 使用反射機制解決
        //(1) 加載類, 返回Class類型的對象cls
        Class cls = Class.forName(classfullpath);
        //(2) 通過 cls 得到你加載的類 com.hspedu.Cat 的對象實例
        Object o = cls.newInstance();
        System.out.println("o的運行類型=" + o.getClass()); //運行類型
        //(3) 通過 cls 得到你加載的類 com.hspedu.Cat 的 methodName"hi"  的方法對象
        //    即:在反射中,可以把方法視為對象(萬物皆對象)
        Method method1 = cls.getMethod(methodName);
        //(4) 通過method1 調(diào)用方法: 即通過方法對象來實現(xiàn)調(diào)用方法
        System.out.println("=============================");
        method1.invoke(o); //傳統(tǒng)方法 對象.方法() , 反射機制 方法.invoke(對象)
    }
}

反射的需求

Java反射機制的需求主要有以下幾個方面:

  1. 動態(tài)加載類和調(diào)用類方法:通過反射機制,可以在運行時動態(tài)的加載一個類,并調(diào)用該類的方法。這種方式可以實現(xiàn)更加靈活的代碼編寫,避免了在編譯期就要確定所有的類和方法的限制。
  2. 實現(xiàn)通用框架:通過反射機制,可以實現(xiàn)通用的框架,比如ORM(對象-關系映射)框架、依賴注入框架、AOP(面向切面編程)框架等。這些框架需要在運行時動態(tài)的獲取類的信息,然后進行相應的操作。
  3. 修改類的屬性和方法:通過反射機制,可以在運行時修改類的屬性和方法,從而實現(xiàn)更加靈活的代碼編寫。
  4. 實現(xiàn)序列化和反序列化:Java中的序列化和反序列化需要用到反射機制,通過反射機制可以獲取對象的屬性和方法,然后將其序列化為字節(jié)流或者反序列化為對象。
  5. 動態(tài)代理:通過反射機制,可以實現(xiàn)動態(tài)代理,即在運行時生成一個代理對象,通過代理對象來調(diào)用目標對象的方法,從而實現(xiàn)AOP等功能。

那么我們使用反射機制可以完成

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

2.在運行時構(gòu)造任意一個類的對象

3.在運行時得到任意一個類所具有的成員變量和方法

4.在運行時調(diào)用任意一個對象的成員變量和方法

5.生成動態(tài)代理

反射相關的主要類

1.java.lang.Class:代表一個類,Class對象表示某個類加載后在堆中的對象

2.java.lang.reflect.Method: 代表類的方法, Method對象表示某個類的方法

3.java.lang.reflect.Field: 代表類的成員變量,Field對象表示某個類的成員變量

4.java.lang.reflect.Constructor: 代表類的構(gòu)造方法,Constructor對象表示構(gòu)造器

代碼演示:

注意:反射和我們正常的使用方式有些不同,我們正常調(diào)用方法時對象名.方法名,但是在反射中是 方法名.對象名這里要注意一下

package com.reflection;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
@SuppressWarnings({"all"})
public class Reflection01 {
    public static void main(String[] args) throws Exception {
        //1. 使用Properties 類, 可以讀寫配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat"
        String methodName = properties.get("method").toString();//"hi"
        //2. 使用反射機制解決
        //(1) 加載類, 返回Class類型的對象cls
        Class cls = Class.forName(classfullpath);
        //(2) 通過 cls 得到你加載的類 com.hspedu.Cat 的對象實例
        Object o = cls.newInstance();
        System.out.println("o的運行類型=" + o.getClass()); //運行類型
        //(3) 通過 cls 得到你加載的類 com.hspedu.Cat 的 methodName"hi"  的方法對象
        //    即:在反射中,可以把方法視為對象(萬物皆對象)
        Method method1 = cls.getMethod(methodName);
        //(4) 通過method1 調(diào)用方法: 即通過方法對象來實現(xiàn)調(diào)用方法
        System.out.println("=============================");
        method1.invoke(o); //傳統(tǒng)方法 對象.方法() , 反射機制 方法.invoke(對象)
        //java.lang.reflect.Field: 代表類的成員變量, Field對象表示某個類的成員變量
        //得到name字段
        //getField不能得到私有的屬性
        Field nameField = cls.getField("age"); //
        System.out.println(nameField.get(o)); // 傳統(tǒng)寫法 對象.成員變量 , 反射 :  成員變量對象.get(對象)
        //java.lang.reflect.Constructor: 代表類的構(gòu)造方法, Constructor對象表示構(gòu)造器
        Constructor constructor = cls.getConstructor(); //()中可以指定構(gòu)造器參數(shù)類型, 返回無參構(gòu)造器
        System.out.println(constructor);//Cat()
        Constructor constructor2 = cls.getConstructor(String.class); //這里傳入的 String.class 就是String類的Class對象
        System.out.println(constructor2);//Cat(String name)
    }
}

反射優(yōu)點和缺點

優(yōu)點:

  • 動態(tài)性:Java反射機制可以在運行時動態(tài)地獲取類的信息和操作對象,使程序更加靈活和易于擴展。
  • 通用性:可以通過反射機制操作任意類型的對象,無需知道對象的具體類型。
  • 代碼復用性:反射機制可以讓代碼更加通用和復用,提高開發(fā)效率。
  • AOP支持:反射機制是實現(xiàn)AOP(面向切面編程)的重要手段之一。

缺點:

  • 性能較低:Java反射機制需要在運行時動態(tài)地獲取對象信息和方法,需要一定的時間開銷,因此性能較低。
  • 安全問題:反射機制可以操作任意類型的對象,容易造成安全問題,需要謹慎使用,并在必要時進行安全檢查。
  • 可讀性下降:由于反射機制支持動態(tài)的獲取和操作對象,因此代碼的可讀性會下降一些,需要謹慎使用。
  • 不利于編譯器優(yōu)化:由于反射機制需要在運行時動態(tài)獲取對象信息和方法,因此編譯器很難對代碼進行優(yōu)化。

代碼演示;

在下面的代碼中 ,我們分別測試了,使用正常的方式去調(diào)用方法,和使用反射的方式去調(diào)用方法,并且在執(zhí)行方法開始之前記錄了開始時間,在方法執(zhí)行結(jié)束之后,記錄了結(jié)束時間,最后兩個相減,就可以得到方法的執(zhí)行時間,我們就可以看出,使用正常的方式去調(diào)用方法,和使用反射的方式去調(diào)用方法,的區(qū)別。

package com.reflection;
import com.Cat;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
 * 測試反射調(diào)用a的性能,和優(yōu)化方案
 */
public class Reflection02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //Field
        //Method
        //Constructor
        m1();
        m2();
        m3();
    }
    //傳統(tǒng)方法來調(diào)用hi
    public static void m1() {
        Cat cat = new Cat();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 90; i++) {
            cat.hi();
        }
        long end = System.currentTimeMillis();
        System.out.println("m1() 耗時=" + (end - start));
    }
    //反射機制調(diào)用方法hi
    public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class cls = Class.forName("com.Cat");
        Object o = cls.newInstance();
        Method hi = cls.getMethod("hi");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000000; i++) {
            hi.invoke(o);//反射調(diào)用方法
        }
        long end = System.currentTimeMillis();
        System.out.println("m2() 耗時=" + (end - start));
    }
    //反射調(diào)用優(yōu)化 + 關閉訪問檢查
    public static void m3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class cls = Class.forName("com.Cat");
        Object o = cls.newInstance();
        Method hi = cls.getMethod("hi");
        hi.setAccessible(true);//在反射調(diào)用方法時,取消訪問檢查
        long start = System.currentTimeMillis();
        for (int i = 0; i < 900000000; i++) {
            hi.invoke(o);//反射調(diào)用方法
        }
        long end = System.currentTimeMillis();
        System.out.println("m3() 耗時=" + (end - start));
    }
}

反射調(diào)用優(yōu)化

Java中反射調(diào)用通常比直接調(diào)用方法緩慢,因為它需要進行額外的動態(tài)類型檢查和查找。為了優(yōu)化反射調(diào)用,可以采用以下幾種方法:

緩存Method對象:通過緩存Method對象,避免動態(tài)查找,提高調(diào)用效率。

使用方法句柄(MethodHandle):方法句柄是一種更高效的調(diào)用機制,它可以繞過反射調(diào)用的開銷。方法句柄比反射調(diào)用更快,特別是在熱代碼路徑上。

使用invokedynamic指令:為了提高反射調(diào)用的性能,Java 7引入了invokedynamic指令。它允許動態(tài)綁定方法調(diào)用,避免了反射調(diào)用的開銷。

使用字節(jié)碼生成庫:字節(jié)碼生成庫可以生成字節(jié)碼,從而避免了反射調(diào)用的開銷。比如,cglib是一個非常常用的字節(jié)碼生成庫。

到此這篇關于Java中反射機制的使用詳解的文章就介紹到這了,更多相關Java反射機制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring實現(xiàn)動態(tài)數(shù)據(jù)源切換的方法總結(jié)

    Spring實現(xiàn)動態(tài)數(shù)據(jù)源切換的方法總結(jié)

    這篇文章主要為大家詳細介紹了一種Spring實現(xiàn)動態(tài)數(shù)據(jù)源切換的方法,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以跟隨小編一起了解一下
    2023-06-06
  • Jpa使用Page和Pageable分頁遇到的問題及解決

    Jpa使用Page和Pageable分頁遇到的問題及解決

    這篇文章主要介紹了Jpa使用Page和Pageable分頁遇到的問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Springboot的yml配置文件用法

    Springboot的yml配置文件用法

    這篇文章主要介紹了Springboot的yml配置文件用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java中常見的4種限流算法詳解

    Java中常見的4種限流算法詳解

    這篇文章主要介紹了Java中常見的4種限流算法詳解,FixedWindowRateLimiter 類表示一個固定窗口限流器,使用 limit 和 interval 參數(shù)分別表示限制請求數(shù)量和時間間隔,缺點是短時間內(nèi)可能會流量翻倍,需要的朋友可以參考下
    2023-12-12
  • SpringBoot中調(diào)用通用URL的實現(xiàn)

    SpringBoot中調(diào)用通用URL的實現(xiàn)

    在 Spring Boot 應用程序中,有時候我們需要調(diào)用一些通用的 URL 接口,本文主要介紹了SpringBoot中調(diào)用通用URL的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • Java 多線程實例詳解(二)

    Java 多線程實例詳解(二)

    本文主要介紹Java 多線程的資料整理,這里整理了詳細資料及相關示例代碼,有興趣的小伙伴可以參考下
    2016-09-09
  • spring事物傳播propagation類別含義詳解

    spring事物傳播propagation類別含義詳解

    這篇文章主要介紹了spring事物傳播propagation類別含義詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • 詳解Java并發(fā)編程之原子類

    詳解Java并發(fā)編程之原子類

    這篇文章主要為大家介紹了Java并發(fā)編程之原子類介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • 實例講解Java設計模式編程中如何運用代理模式

    實例講解Java設計模式編程中如何運用代理模式

    這篇文章主要介紹了Java設計模式編程中如何運用代理模式,文中舉了普通代理和強制代理的例子作為代理模式的擴展內(nèi)容,需要的朋友可以參考下
    2016-02-02
  • 關于java String中intern的深入講解

    關于java String中intern的深入講解

    這篇文章主要給大家介紹了關于java String中intern的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-04-04

最新評論