最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java反射機(jī)制基礎(chǔ)詳解

 更新時(shí)間:2021年08月11日 16:38:19   作者:smileNicky  
這篇文章主要介紹了JAVA 反射機(jī)制的相關(guān)知識(shí),文中講解的非常細(xì)致,代碼幫助大家更好的理解學(xué)習(xí),感興趣的朋友可以了解下,希望能給你帶來(lái)幫助

1、什么是Java反射機(jī)制?

在程序運(yùn)行中動(dòng)態(tài)地獲取類的相關(guān)屬性,同時(shí)調(diào)用對(duì)象的方法和獲取屬性,這種機(jī)制被稱之為Java反射機(jī)制

下面給出一個(gè)反射的簡(jiǎn)單例子:

import lombok.Data;

@Data
public class User {

    public String username;
    private String password;

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
public static void reflectionSimpleExample() throws Exception{
    User user = new User();
    System.out.println(user.toString());
	// 獲取對(duì)應(yīng)類的class
    Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
    Object obj = cls.newInstance();
    System.out.println(obj);
	// 獲取成員變量,注意要是public的
    Field field = cls.getField("username");
    System.out.println(field.get(obj));

}

2、反射機(jī)制原理

Java反射是Java實(shí)現(xiàn)動(dòng)態(tài)語(yǔ)言的關(guān)鍵,也就是通過(guò)反射實(shí)現(xiàn)類動(dòng)態(tài)加載

靜態(tài)加載: 在編譯時(shí)加載相關(guān)的類,如果找不到類就會(huì)報(bào)錯(cuò),依賴性比較強(qiáng)動(dòng)態(tài)加載:在運(yùn)行時(shí)加載需要的類,在項(xiàng)目跑起來(lái)之后,調(diào)用才會(huì)報(bào)錯(cuò),降低了依賴性

例子:靜態(tài)加載,如下代碼,如果找不到類的情況,代碼編譯都不通過(guò)

User user = new User();

而動(dòng)態(tài)加載,就是反射的情況,是可以先編譯通過(guò)的,然后在調(diào)用代碼時(shí)候,也就是運(yùn)行時(shí)才會(huì)報(bào)錯(cuò)

 Class<?> cls = Class.forName("com.example.core.example.reflection.User");
Object obj = cls.newInstance();

Exception in thread “main” java.lang.ClassNotFoundException: com.example.core.example.reflection.User

java中的反射允許程序在執(zhí)行期借助jdk中Reflection API來(lái)獲取類的內(nèi)部信息,比如成員變量、成員方法、構(gòu)造方法等等,并能操作類的屬性和方法

java中反射的實(shí)現(xiàn)和jvm和類加載機(jī)制有一定的關(guān)系,加載好類之后,在jvm的堆中會(huì)產(chǎn)生一個(gè)class類型的對(duì)象,這個(gè)class類包括了類的完整結(jié)構(gòu)信息,通過(guò)這個(gè)class對(duì)象就可以獲取到類的結(jié)構(gòu)信息,所以形象地稱之為java反射

在這里插入圖片描述

3、Class類介紹

3.1、Class類基本介紹

然后這個(gè)Class類是什么?看下uml類圖:

在這里插入圖片描述

Class也是類,因此也繼承Object類

Class不是直接new出來(lái)的,而是經(jīng)過(guò)系統(tǒng)創(chuàng)建的

User user = new User();

打個(gè)斷點(diǎn),debug進(jìn)行看看源碼,可以看到傳統(tǒng)的直接new一個(gè)對(duì)象也是通過(guò)類加載器loadClass拿到的

在這里插入圖片描述

java反射方式,通用通過(guò)調(diào)試看看:

 Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");

同樣本質(zhì)也是通過(guò)ClassLoad再通過(guò)類的全類名

在這里插入圖片描述

3.2、Class類對(duì)象的獲取方法 Class.forname()

Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");

應(yīng)用場(chǎng)景:多用于讀取類全路徑,加載類

具體類.class
已經(jīng)知道具體類的情況,通過(guò)具體類的class屬性獲取

Class u = User.class;

應(yīng)用場(chǎng)景:多用于用于參數(shù)傳遞

對(duì)象.getClass
已經(jīng)創(chuàng)建好對(duì)象的情況,直接通過(guò)對(duì)象實(shí)例獲取class對(duì)象

Class cls = user.getClass();

應(yīng)用場(chǎng)景:通過(guò)創(chuàng)建好的對(duì)象,獲取Class對(duì)象

ClassLoader獲取

ClassLoader cl = user.getClass().getClassLoader();
Class cls = cl.loadClass("com.example.core.example.reflection.domain.User");

基本數(shù)據(jù)類型

Class cls = int.class;

包裝類

基本數(shù)據(jù)類型對(duì)應(yīng)的包裝類可以通過(guò).TYPE得到Class類對(duì)象

Class cls = Integer.TYPE;

3.3 、可以獲取Class對(duì)象的類型

1、外部類,成員內(nèi)部類,靜態(tài)內(nèi)部類,局部?jī)?nèi)部類,匿名內(nèi)部類

2、interface:接口

3、數(shù)組

4、enum:枚舉

5、annotation:注解

6、基本數(shù)據(jù)類型

7、void8、Class… ,等等

import com.example.core.example.reflection.domain.User;
import lombok.ToString;

import java.util.List;

public class GetClassObjectExample {

    public static void main(String[] args) {
        // 外部類
        Class<User> cls1 = User.class;
        // 接口
        Class<List> cls2 = List.class;
        // 數(shù)組
        Class<Integer[]> cls3 = Integer[].class;
        // 二維數(shù)組
        Class<String[][]> cls4 = String[][].class;
        // 注解
        Class<lombok.ToString> cls5 = ToString.class;

        // 枚舉
        Class<Thread.State> cls6 = Thread.State.class;
        // 基本數(shù)據(jù)類型
        Class<Long> cls7 = Long.class;
        // void 數(shù)據(jù)類型
        Class<Void> cls8 = Void.class;
        // Class
        Class<Class> cls9 = Class.class;

        System.out.println(cls1);
        System.out.println(cls2);
        System.out.println(cls3);
        System.out.println(cls4);
        System.out.println(cls5);
        System.out.println(cls6);
        System.out.println(cls7);
        System.out.println(cls8);
        System.out.println(cls9);
    }
}

4、java反射的作用?

可以通過(guò)外部類的全路徑名創(chuàng)建對(duì)象,并使用這些類可以枚舉出類的全部成員,包括構(gòu)造函數(shù)、屬性、方法利用反射 API 訪問(wèn)類的私有成員

5、反射API主要類

1、java.lang.Class:代表一個(gè)類,表示某個(gè)類在jvm堆中的對(duì)象

2、 java.lang.reflect.Method:代表類的方法

3、 java.lang.reflect.Field:代表類的成員變量

4、 java.lang.reflect.Constructor:代表類額構(gòu)造方法

6、Java反射的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):使用Java反射可以靈活動(dòng)態(tài)地創(chuàng)建和使用對(duì)象,反射是框架的底層支撐缺點(diǎn):使用Java反射,基本就是解釋執(zhí)行的,對(duì)執(zhí)行速度是有影響的

7、反射調(diào)用的優(yōu)化方法

前面介紹了Java反射雖然很靈活,但是缺點(diǎn)就是調(diào)用時(shí)候比較慢,相對(duì)直接new對(duì)象來(lái)說(shuō),情況是怎么樣的?下面通過(guò)例子進(jìn)行試驗(yàn):

import com.example.core.example.reflection.domain.User;

import java.lang.reflect.Method;

public class TestReflectionExample {

    private static final Integer TOTAL_COUNT = 1000000;

    public static void main(String[] args) throws Exception{
        test0();
        test1();
        test2();
    }

    public static void test0() {
        long start = System.currentTimeMillis();
        User user = new User();
        for (int i = 0 ; i < TOTAL_COUNT; i++) {
            user.hello();
        }
        System.out.println(String.format("傳統(tǒng)調(diào)用方法執(zhí)行時(shí)間:%d" , System.currentTimeMillis() - start));
    }

    public static void test1() throws Exception{
        long start = System.currentTimeMillis();
        Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
        Object obj = cls.newInstance();
        Method hello = cls.getMethod("hello");
        for (int i = 0 ; i < TOTAL_COUNT; i++) {
            hello.invoke(obj);
        }
        System.out.println(String.format("反射方法調(diào)用執(zhí)行時(shí)間:%d" , System.currentTimeMillis() - start));
    }

    public static void test2() throws Exception{
        long start = System.currentTimeMillis();
        Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
        Object obj = cls.newInstance();
        Method hello = cls.getMethod("hello");
        // 關(guān)鍵,取消調(diào)用反射方法時(shí)的安全檢查
        hello.setAccessible(true);
        for (int i = 0 ; i < TOTAL_COUNT; i++) {
            hello.invoke(obj);
        }
        System.out.println(String.format("優(yōu)化后的反射方法調(diào)用執(zhí)行時(shí)間:%d" , System.currentTimeMillis() - start));
    }
}

傳統(tǒng)調(diào)用方法執(zhí)行時(shí)間:19
反射方法調(diào)用執(zhí)行時(shí)間:112
優(yōu)化后的反射方法調(diào)用執(zhí)行時(shí)間:50

8、反射的基本使用例子

java.lang.Class類

方法名 作用
getName 獲取全類名
getSimpleName 獲取簡(jiǎn)單類名
getFields 獲取所有public修飾的屬性、包括本類以及父類的
getDeclaredFields 獲取本類中所有的屬性
getMethods 獲取所有的public修飾的方法,包括本類以及父類的
getDeclaredMethod 獲取本類中所有方法
getConstructors 獲取所有public修飾的構(gòu)造器,只有本類
getDeclaredConstructors 獲取本類中所有構(gòu)造器
getPackage Package形式返回 包信息
getSuperClass Class形式返回父信息
getInterfaces Class[]形式返回父接口信息
getAnnotations Annotation[]形式返回注解信息
String allClassName = "com.example.core.example.reflection.domain.User";
// 通過(guò)全類名獲取class對(duì)象
Class<?> cls = Class.forName(allClassName);
System.out.println(cls);
// 通過(guò)對(duì)象獲取class
System.out.println(cls.getClass());
// 獲取全類名
System.out.println(cls.getName());
// 獲取包名
System.out.println(cls.getClass().getPackage().getName());
// 獲取對(duì)象實(shí)例
Object obj = cls.newInstance();
System.out.println(obj);

java.lang.reflect.Field類

方法名 作用
getModifiers 以int形式返回修飾符,默認(rèn)修飾符是0,public是1,private是2,protected是4,static是8,final是16
getType 以Class形式返回類型
getName 返回屬性名稱
// 獲取類屬性
Field field = cls.getField("username");
field.set(obj , "admin");
System.out.println(field.get(obj));
// 獲取所有類屬性,private的成員變量沒(méi)有權(quán)限訪問(wèn)
Field[] fields = cls.getFields();
for (Field field1 : fields) {
    System.out.println(field1.get(obj));
}
// 獲取所有類屬性包括private成員變量
Field[] allFields = cls.getDeclaredFields();
for (Field afield : allFields) {
    // 開放權(quán)限,私有的成員變量也能打印出來(lái)
    afield.setAccessible(true);
    System.out.println(afield.get(obj));
}

java.lang.reflect.Method類

方法名 作用
getModifiers 以int形式返回修飾符,默認(rèn)修飾符是0,public是1,private是2,protected是4,static是8,final是16
getName 返回方法名
getReturnType 以class形式返回類型
getParmeterTypes 以Class[] 返回參數(shù)類型數(shù)組
// 獲取class方法,同樣默認(rèn)情況不能獲取private的方法
Method method = cls.getMethod("hello");
System.out.println(method.invoke(obj));

java.lang.reflect.Constructor類

方法名 作用
getModifiers 以int形式返回修飾符,默認(rèn)修飾符是0,public是1,private是2,protected是4,static是8,final是16
getName 返回方法名
getParmeterTypes 以Class[] 返回參數(shù)類型數(shù)組
Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
Constructor<?> con = cls.getDeclaredConstructor();
con.setAccessible(true);
Object obj = con.newInstance();
System.out.println(obj);

9、反射開放權(quán)限操作

在我們使用Java反射獲取class的private成員變量或者方法時(shí),這種情況是不允許獲取的,不過(guò)可以通過(guò)開放權(quán)限的方式來(lái)處理,通過(guò)設(shè)置setAccessible(true);即可

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * <pre>
 *      開放java反射權(quán)限,允許調(diào)用類的private屬性或者方法
 * </pre>
 * <p>
 * <pre>
 * @author mazq
 * 修改記錄
 *    修改后版本:     修改人:  修改日期: 2021/08/09 19:10  修改內(nèi)容:
 * </pre>
 */
public class AccessibleReflectionExample {

    public static void main(String[] args) throws Exception{

        test();
    }

    public static void test() throws Exception{
        // 創(chuàng)建class實(shí)例對(duì)象
        Class<?> cls = Class.forName("com.example.core.example.reflection.domain.User");
        Constructor<?> con = cls.getDeclaredConstructor();
        con.setAccessible(true);
        Object obj = con.newInstance();

        // 獲取私有成員變量
        Field pwd = cls.getDeclaredField("password");
        // 開放私有變量的訪問(wèn)權(quán)限
        pwd.setAccessible(true);
        pwd.set(obj , "123456");

        // 私有方法調(diào)用
        Method method = cls.getDeclaredMethod("priToString");
        method.setAccessible(true);
        System.out.println(method.invoke(obj));
    }
}

總結(jié)

本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • spring中的事務(wù)執(zhí)行流程圖解

    spring中的事務(wù)執(zhí)行流程圖解

    這篇文章主要介紹了spring中的事務(wù)執(zhí)行流程圖解,Spring事務(wù)是Spring框架提供的一種管理數(shù)據(jù)庫(kù)事務(wù)的機(jī)制,它通過(guò)將一系列數(shù)據(jù)庫(kù)操作封裝在一個(gè)事務(wù)中,保證這些操作要么全部成功執(zhí)行,要么全部回滾,從而確保數(shù)據(jù)的一致性和完整性,需要的朋友可以參考下
    2023-10-10
  • Java多線程同步工具類CyclicBarrier的使用

    Java多線程同步工具類CyclicBarrier的使用

    本文主要介紹了Java多線程同步工具類CyclicBarrier的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Java中Minio的基本使用詳解

    Java中Minio的基本使用詳解

    這篇文章主要介紹了Java中Minio的基本使用詳解,MinIO 是一個(gè)基于Apache License v2.0開源協(xié)議的對(duì)象存儲(chǔ)服務(wù),它兼容亞馬遜S3云存儲(chǔ)服務(wù)接口,非常適合于存儲(chǔ)大容量非結(jié)構(gòu)化的數(shù)據(jù),例如圖片、視頻、日志文件、備份數(shù)據(jù)和容器/虛擬機(jī)鏡像等,需要的朋友可以參考下
    2024-01-01
  • 關(guān)于java入門與java開發(fā)環(huán)境配置詳細(xì)教程

    關(guān)于java入門與java開發(fā)環(huán)境配置詳細(xì)教程

    這篇文章主要介紹了關(guān)于java入門與java開發(fā)環(huán)境配置詳細(xì)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • JAVA基于數(shù)組實(shí)現(xiàn)的商品信息查詢功能示例

    JAVA基于數(shù)組實(shí)現(xiàn)的商品信息查詢功能示例

    這篇文章主要介紹了JAVA基于數(shù)組實(shí)現(xiàn)的商品信息查詢功能,結(jié)合實(shí)例形式詳細(xì)分析了java使用數(shù)組存儲(chǔ)數(shù)據(jù)實(shí)現(xiàn)的商品信息查詢功能相關(guān)操作技巧,需要的朋友可以參考下
    2019-11-11
  • SpringMVC表單提交參數(shù)400錯(cuò)誤解決方案

    SpringMVC表單提交參數(shù)400錯(cuò)誤解決方案

    這篇文章主要介紹了SpringMVC表單提交參數(shù)400錯(cuò)誤解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • gradle和maven有哪些區(qū)別

    gradle和maven有哪些區(qū)別

    這篇文章主要介紹了gradle和maven有哪些區(qū)別,幫助大家更好的理解和選擇java程序的構(gòu)建工具,感興趣的朋友可以了解下
    2021-01-01
  • 詳解WebSocket+spring示例demo(已使用sockJs庫(kù))

    詳解WebSocket+spring示例demo(已使用sockJs庫(kù))

    本篇文章主要介紹了WebSocket spring示例demo(已使用sockJs庫(kù)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • java編程之單元測(cè)試(Junit)實(shí)例分析(附實(shí)例源碼)

    java編程之單元測(cè)試(Junit)實(shí)例分析(附實(shí)例源碼)

    這篇文章主要介紹了java編程之單元測(cè)試(Junit),結(jié)合實(shí)例形式較為詳細(xì)的分析總結(jié)了Java單元測(cè)試的原理、步驟及相關(guān)注意事項(xiàng),并附帶了完整代碼供讀者下載參考,需要的朋友可以參考下
    2015-11-11
  • springboot配置多數(shù)據(jù)源的一款框架(dynamic-datasource-spring-boot-starter)

    springboot配置多數(shù)據(jù)源的一款框架(dynamic-datasource-spring-boot-starter

    dynamic-datasource-spring-boot-starter 是一個(gè)基于 springboot 的快速集成多數(shù)據(jù)源的啟動(dòng)器,今天通過(guò)本文給大家分享這款框架配置springboot多數(shù)據(jù)源的方法,一起看看吧
    2021-09-09

最新評(píng)論

阿合奇县| 泰来县| 汶上县| 册亨县| 襄垣县| 扎赉特旗| 靖西县| 萨嘎县| 临夏市| 密云县| 册亨县| 武平县| 肃宁县| 阳西县| 通化县| 师宗县| 招远市| 平谷区| 安陆市| 临江市| 都江堰市| 霍山县| 丁青县| 三明市| 高雄市| 天台县| 遵义县| 彰化市| 远安县| 晋城| 三明市| 泾阳县| 大化| 资中县| 尖扎县| 东明县| 炉霍县| 金昌市| 朝阳区| 定州市| 文登市|