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

一文搞懂Java中的反射機(jī)制

 更新時(shí)間:2022年07月19日 09:23:13   作者:XH學(xué)Java  
Java的反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任何一個(gè)類(lèi),都可以知道這個(gè)類(lèi)的所有屬性和方法,對(duì)于任何一個(gè)對(duì)象,都可以調(diào)用它所有的方法和屬性,修改部分類(lèi)型信息。本文就來(lái)詳細(xì)講講Java反射機(jī)制的使用

一. 反射的概念

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

二. 為什么需要反射

在日常的第三方開(kāi)發(fā)中,經(jīng)常遇到某個(gè)類(lèi)的方法或?qū)傩允撬接械模@時(shí)候就可以利用反射機(jī)制來(lái)獲取所需要的私有方法或?qū)傩?/p>

我們?cè)谶M(jìn)行Java程序開(kāi)發(fā)時(shí),為了開(kāi)發(fā)效率,一般會(huì)選擇IDE開(kāi)發(fā)環(huán)境,IDE開(kāi)發(fā)環(huán)境有一個(gè)強(qiáng)大的功能就是自動(dòng)提示功能,IDE是如何知道對(duì)象中有哪些屬性和方法呢?

反射最重要的用途就是開(kāi)發(fā)各種通用框架,比如在spring中,我們將所有的類(lèi)Bean交給spring容器管理,無(wú)論是XML配置Bean還是注解配置,當(dāng)我們從容器中獲取Bean來(lái)依賴(lài)注入時(shí),容器會(huì)讀取配置,而配置中給的就是類(lèi)的信息,spring根據(jù)這些信息,需要?jiǎng)?chuàng)建那些Bean,spring就動(dòng)態(tài)的創(chuàng)建這些類(lèi)

三. 反射的基石

反射的基石是字節(jié)碼文件對(duì)象

Java的源文件是不能直接進(jìn)行運(yùn)行的,需要先進(jìn)行編譯為.class的字節(jié)碼文件,然后使用雙親委派模型被類(lèi)加載器加載到虛擬機(jī)中形成字節(jié)碼文件對(duì)象,才可以在JVM中運(yùn)行

何時(shí)才能觸發(fā)類(lèi)的加載呢?只要需要用類(lèi)就會(huì)觸發(fā)類(lèi)的加載,比如:

  1. new一個(gè)對(duì)象的時(shí)候
  2. 訪問(wèn)一個(gè)靜態(tài)成員的時(shí)候
  3. 訪問(wèn)一個(gè)靜態(tài)方法的時(shí)候
  4. 創(chuàng)建一個(gè)子類(lèi)對(duì)象的時(shí)候
  5. java命令執(zhí)行一個(gè)字節(jié)碼文件的時(shí)候
  6. 通過(guò)反射機(jī)制創(chuàng)建一個(gè)字節(jié)碼文件對(duì)象的時(shí)候

在Java中,一切皆對(duì)象,當(dāng)字節(jié)碼文件加載到JVM中,會(huì)形成一個(gè)Class類(lèi)對(duì)象,即該類(lèi)在jvm中變成了一個(gè)對(duì)象

字節(jié)碼文件對(duì)象包含了三部分內(nèi)容:

構(gòu)造方法---Constructor對(duì)象

成員方法---Method對(duì)象

成員變量---Filed對(duì)象

四. 反射的實(shí)現(xiàn)

反射的第一步就是先獲取Class類(lèi)對(duì)象,也就是字節(jié)碼文件對(duì)象,然后通過(guò)Class對(duì)象的核心方法達(dá)到反射的目的

1. 獲取字節(jié)碼文件對(duì)象 

獲取Class對(duì)象有三種方式:

  • 使用Class.forName("類(lèi)的全路徑名"),可能會(huì)拋出ClassNotFoundException異常
  • 使用類(lèi)名.class,需要在編譯期間就明確要操作的類(lèi)
  • 使用對(duì)象.getClass()方法,需要先將對(duì)象創(chuàng)建出類(lèi)

先創(chuàng)建一個(gè)Student類(lèi),將它的屬性,方法都設(shè)置為私有的

public class Student {
    private String name;
    private int age;
 
     public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    private String getName() {
        return name;
    }
 
    private void setName(String name) {
        this.name = name;
    }
 
    private int getAge() {
        return age;
    }
 
    private void setAge(int age) {
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

這時(shí)候,Student類(lèi)的全路徑名為:反射枚舉lambda.Student 

下面是獲取字節(jié)碼對(duì)象三種方式的代碼展示:

public class TestReflect {
    public static void main(String[] args) {
        //獲取字節(jié)碼文件對(duì)象
        //1.使用Class.forName("類(lèi)的全路徑")
        try {
            Class<?> stuClass1 = Class.forName("反射枚舉lambda.Student");
            System.out.println(stuClass1);
            //2.使用類(lèi).class
            Class<?> stuClass2 = Student.class;
            System.out.println(stuClass2);
            System.out.println(stuClass1==stuClass2); //true,字節(jié)碼文件只有一份,故是同一個(gè)對(duì)象
            //3.使用對(duì)象.getClass()
            //該方法需要先創(chuàng)建對(duì)象,故先將Student類(lèi)的構(gòu)造方法改為公有的再進(jìn)行下述操作
            Student student = new Student("張三",26);
            Class<?> stuClass3 = student.getClass();
            System.out.println(stuClass3);
            System.out.println(stuClass2==stuClass3); //true,字節(jié)碼文件只有一份,故是同一個(gè)對(duì)象
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

打印結(jié)果:字節(jié)碼文件只有一份,所以不同方式獲得的是同一個(gè)對(duì)象

2. 反射的使用 

2.1 反射構(gòu)造方法創(chuàng)建實(shí)例

與反射相關(guān)的包都在import java.lang.reflect包下面

方法說(shuō)明
Constructor[] getConstructors()獲取類(lèi)中所有公有的構(gòu)造器對(duì)象
Constructor<T> getConstructors(Class...<T> paramTypes)獲取參數(shù)匹配的共有的構(gòu)造器對(duì)象
Constructor[] getDeclaredConstructors()獲取類(lèi)中所有的構(gòu)造器對(duì)象,包括私有的
Constructor<T> getDeclaredConstructors(Class...<T> paramTypes)獲取類(lèi)中參數(shù)匹配的構(gòu)造器對(duì)象,包括私有的

具體步驟:

  • 獲取字節(jié)碼文件對(duì)象
  • 使用字節(jié)碼對(duì)象獲取構(gòu)造方法
  • 設(shè)置構(gòu)造方法權(quán)限
  • 使用構(gòu)造方法創(chuàng)建實(shí)例對(duì)象 

代碼示例:

    public static void main(String[] args) {
        try {
            //1.獲取字節(jié)碼對(duì)象
            Class<?> stuClass = Class.forName("反射枚舉lambda.Student");
            //2.獲取構(gòu)造方法
            Constructor<?> stuConstructor = stuClass.getDeclaredConstructor(String.class,int.class); //參數(shù)也是class類(lèi)型
            //3.修改方法的訪問(wèn)權(quán)限
            stuConstructor.setAccessible(true);
            //4.調(diào)用該方法
            Object object = stuConstructor.newInstance("李四",23); //newInstance()創(chuàng)建類(lèi)的實(shí)例,為Object類(lèi)型 
            Student s = (Student) object;
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

打印結(jié)果:

  

2.2 反射屬性

方法說(shuō)明
getFields()獲取所有公有的屬性對(duì)象
getField(String name)獲取某個(gè)公有的屬性對(duì)象
getDeclaredFields()獲取所有的屬性對(duì)象,包括私有屬性
getDeclaredField(String name)獲取某個(gè)屬性對(duì)象,包括私有屬性

具體步驟:

  • 獲取字節(jié)碼對(duì)象
  • 使用字節(jié)碼對(duì)象獲取屬性
  • 設(shè)置屬性權(quán)限
  • 調(diào)用方法設(shè)置屬性值

代碼示例:

//反射屬性
Field sutAge = stuClass.getDeclaredField("age"); //參數(shù)為屬性
sutAge.setAccessible(true);
sutAge.setInt(s,18); //設(shè)置屬性值為int,第一個(gè)參數(shù)為哪個(gè)對(duì)象,第二個(gè)參數(shù)為設(shè)置值
System.out.println(s);

打印結(jié)果:將對(duì)象s的age設(shè)置為18

2.3 反射方法

方法說(shuō)明
getMethods()獲取該類(lèi)所有的公有的方法
getMethod(String name,Class...<?> parameterTypes)獲取該類(lèi)某個(gè)公有的方法
getDeclaredMethods()獲取該類(lèi)所有方法,包括私有
getDeclaredMethod(String name,Class...<?> parameterTypes)獲取該類(lèi)某個(gè)方法,包括私有

具體步驟:

  • 獲取字節(jié)碼對(duì)象 
  • 使用字節(jié)碼對(duì)象獲取方法
  • 設(shè)置方法權(quán)限
  • 使用方法.invoke調(diào)用,第一個(gè)參數(shù)為哪個(gè)對(duì)象,后面參數(shù)為方法參數(shù)的具體值

代碼示例:

//反射方法
Method setNameMethod = stuClass.getDeclaredMethod("setName", String.class); //第一個(gè)參數(shù)為方法名,后面參數(shù)為方法參數(shù)
setNameMethod.setAccessible(true);
setNameMethod.invoke(s,"王五");
System.out.println(s);

打印結(jié)果:將對(duì)象s的姓名改為王五

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

優(yōu)點(diǎn):

對(duì)于任意一個(gè)類(lèi),可以獲取該類(lèi)的所有屬性和方法,對(duì)于一個(gè)對(duì)象,能調(diào)用它任意一個(gè)方法

增加程序的靈活性和擴(kuò)展性,降低耦合性,提高自適應(yīng)能力

反射已經(jīng)應(yīng)用在很多框架中,如:Spring,Struts,Hibernate 

缺點(diǎn): 

破壞了類(lèi)的封裝性

使用反射導(dǎo)致程序效率低

反射代碼比較復(fù)雜,因而會(huì)帶來(lái)維護(hù)問(wèn)題 

以上就是一文搞懂Java中的反射機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于Java反射機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 新版idea如何開(kāi)啟多臺(tái)JVM虛擬機(jī)的流程步驟

    新版idea如何開(kāi)啟多臺(tái)JVM虛擬機(jī)的流程步驟

    在IntelliJ?IDEA這個(gè)集成開(kāi)發(fā)環(huán)境中(IDE),開(kāi)啟JVM(Java?Virtual?Machine)通常是在運(yùn)行Java應(yīng)用程序時(shí)的操作,本文給大家介紹了新版idea如何開(kāi)啟多臺(tái)JVM虛擬機(jī)的流程步驟,需要的朋友可以參考下
    2024-10-10
  • MyBatis中的JdbcType映射使用介紹

    MyBatis中的JdbcType映射使用介紹

    這篇文章主要介紹了MyBatis中的JdbcType映射使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java編程使用Runtime和Process類(lèi)運(yùn)行外部程序的方法

    Java編程使用Runtime和Process類(lèi)運(yùn)行外部程序的方法

    這篇文章主要介紹了Java編程使用Runtime和Process類(lèi)運(yùn)行外部程序的方法,結(jié)合實(shí)例形式分析了java使用Runtime.getRuntime().exec()方法運(yùn)行外部程序的常見(jiàn)情況與操作技巧,需要的朋友可以參考下
    2017-08-08
  • maven中resource配置的實(shí)現(xiàn)示例

    maven中resource配置的實(shí)現(xiàn)示例

    我們?cè)谑褂肕aven組件來(lái)構(gòu)建項(xiàng)目的時(shí)候,通常將配置文件放在資源文件目錄下,本文主要介紹了maven中resource配置的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Java異常類(lèi)型及處理詳情

    Java異常類(lèi)型及處理詳情

    這篇文章主要介紹了Java異常類(lèi)型及處理, 異常指的是程序在執(zhí)行過(guò)程中,出現(xiàn)了非正常情況,導(dǎo)致了java的jvm停止。感興趣的小伙伴就和小編一起來(lái)學(xué)習(xí)下面文章的具體內(nèi)容吧
    2021-09-09
  • mybatis?plus實(shí)現(xiàn)分頁(yè)邏輯刪除

    mybatis?plus實(shí)現(xiàn)分頁(yè)邏輯刪除

    這篇文章主要為大家介紹了mybatis?plus實(shí)現(xiàn)分頁(yè)邏輯刪除的方式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • 淺談java中null是什么,以及使用中要注意的事項(xiàng)

    淺談java中null是什么,以及使用中要注意的事項(xiàng)

    下面小編就為大家?guī)?lái)一篇淺談java中null是什么,以及使用中要注意的事項(xiàng)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • 為spring get請(qǐng)求添加自定義的參數(shù)處理操作(如下劃線轉(zhuǎn)駝峰)

    為spring get請(qǐng)求添加自定義的參數(shù)處理操作(如下劃線轉(zhuǎn)駝峰)

    這篇文章主要介紹了為spring get請(qǐng)求添加自定義的參數(shù)處理操作(如下劃線轉(zhuǎn)駝峰),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • java-list創(chuàng)建的兩種常見(jiàn)方式

    java-list創(chuàng)建的兩種常見(jiàn)方式

    本文給大家分享Java-list創(chuàng)建的兩種常見(jiàn)方式,每種方式結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • win7 64位系統(tǒng)JDK安裝配置環(huán)境變量教程

    win7 64位系統(tǒng)JDK安裝配置環(huán)境變量教程

    這篇文章主要為大家詳細(xì)介紹了win7 64位系統(tǒng)JDK安裝配置環(huán)境變量教程,感興趣的小伙伴們可以參考一下
    2016-06-06

最新評(píng)論

手机| 湖州市| 昌平区| 北流市| 石棉县| 西和县| 施甸县| 新闻| 鸡西市| 理塘县| 永昌县| 连山| 阜南县| 漳州市| 上犹县| 德清县| 江都市| 富蕴县| 新邵县| 会昌县| 固安县| 堆龙德庆县| 台湾省| 呼伦贝尔市| 汕尾市| 明溪县| 吴堡县| 嫩江县| 平泉县| 永川市| 齐河县| 枝江市| 武乡县| 新疆| 都兰县| 桃园市| 淮南市| 新和县| 兰西县| 江油市| 盘山县|