溫馨提示×

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

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

Java反射的作用是什么

發(fā)布時(shí)間:2021-10-29 15:49:14 來(lái)源:億速云 閱讀:225 作者:iii 欄目:編程語(yǔ)言

這篇文章主要介紹“Java反射的作用是什么”,在日常操作中,相信很多人在Java反射的作用是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Java反射的作用是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

01.解釋型語(yǔ)言和編譯型語(yǔ)言

解釋型語(yǔ)言:不需要編譯,在運(yùn)行的時(shí)候逐行翻譯解釋?zhuān)恍薷拇a時(shí)可以直接修改,可以快速部署,不過(guò)性能上會(huì)比編譯型語(yǔ)言稍差;比如 JavaScript、Python ;

編譯型語(yǔ)言:需要通過(guò)編譯器將源代碼編譯成機(jī)器碼才能執(zhí)行;編譯之后如果需要修改代碼,在執(zhí)行之前就需要重新編譯。比如 C 語(yǔ)言;

Java 嚴(yán)格來(lái)說(shuō)也是編譯型語(yǔ)言,但又介于編譯型和解釋型之間;Java 不直接生成機(jī)器碼而是生成中間碼:編譯期間,是將源碼交給編譯器生成 class 文件(字節(jié)碼),這個(gè)過(guò)程中只做了翻譯的工作,并沒(méi)有把代碼放入內(nèi)存運(yùn)行;當(dāng)進(jìn)入運(yùn)行期,字節(jié)碼才被 Java 虛擬機(jī)加載、解釋成機(jī)器語(yǔ)言并運(yùn)行。

Java反射的作用是什么

02.動(dòng)態(tài)語(yǔ)言和靜態(tài)語(yǔ)言

動(dòng)態(tài)語(yǔ)言:是指程序在運(yùn)行時(shí)可以改變自身結(jié)構(gòu),在運(yùn)行時(shí)確定數(shù)據(jù)類(lèi)型,一個(gè)對(duì)象是否能執(zhí)行某操作,只取決于它有沒(méi)有對(duì)應(yīng)的方法,而不在乎它是否是某種類(lèi)型的對(duì)象;比如 JavaScript、Python。

靜態(tài)語(yǔ)言:相對(duì)于動(dòng)態(tài)語(yǔ)言來(lái)說(shuō),在編譯時(shí)變量的數(shù)據(jù)類(lèi)型就已經(jīng)確定(使用變量之前必須聲明數(shù)據(jù)類(lèi)型),在編譯時(shí)就會(huì)進(jìn)行類(lèi)型是否匹配;比如 C 語(yǔ)言、Java ;

03.反射的概念

Java 反射機(jī)制:在運(yùn)行過(guò)程中,對(duì)于任意一個(gè)類(lèi),都能知道其所有的屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能調(diào)用其屬性和方法;這種動(dòng)態(tài)獲取類(lèi)信息和調(diào)用對(duì)象方法的功能,就是 Java 反射機(jī)制。

既然反射里面有一個(gè)“反”字,那么我們先看看何為“正”。

在 Java 中,要使用一個(gè)類(lèi)中的某個(gè)方法,“正向”都是這樣的:

ArrayList list = new ArrayList(); //實(shí)例化  list.add("reflection");  //執(zhí)行方法

那么反向(反射)要如何實(shí)現(xiàn)?

Class clz = Class.forName("java.util.ArrayList");  Method method_add = clz.getMethod("add",Object.class);  Constructor constructor = clz.getConstructor();  Object object = constructor.newInstance();  method_add.invoke(object, "reflection");  Method method_get = clz.getMethod("get",int.class);  System.out.println(method_get.invoke(object, 0));

兩段代碼執(zhí)行的結(jié)果是一樣的,但是“正向”代碼在編譯前,就已經(jīng)明確了要運(yùn)行的類(lèi)是什么(ArrayList),而第二段代碼,只有在代碼運(yùn)行時(shí),才知道運(yùn)行的類(lèi)是 java.util.ArrayList。

04.反射的作用

講到這里,有些同學(xué)可能會(huì)有疑問(wèn):“反射有什么用?我明明都已經(jīng)知道了要使用的類(lèi)是 ArrayList ,我不能直接 new 一個(gè)對(duì)象然后執(zhí)行里面的方法么?”

當(dāng)然可以!不過(guò)很多場(chǎng)景中,在代碼運(yùn)行之前并不知道需要使用哪個(gè)類(lèi),或者說(shuō)在運(yùn)行的時(shí)候才決定使用哪個(gè)類(lèi);

比如有這么一個(gè)功能:“調(diào)用阿里云的人臉識(shí)別 API ”;這還不簡(jiǎn)單,參考對(duì)方的 API 文檔,很快就能實(shí)現(xiàn)。

Java反射的作用是什么

faceRecognition(Object faceImg){    //調(diào)用阿里云的人臉識(shí)別 API }

上線一個(gè)月后,領(lǐng)導(dǎo)說(shuō):“咱公司開(kāi)始和騰訊云合作了,人臉識(shí)別的接口改一下吧”。

Java反射的作用是什么

faceRecognition(Object faceImg){    //調(diào)用騰訊云的人臉識(shí)別 API  }

修改上線運(yùn)行了兩個(gè)月,領(lǐng)導(dǎo)說(shuō):“換回來(lái)吧”...  ...

當(dāng)然有聰明的程序員會(huì)想到設(shè)置一個(gè)開(kāi)關(guān)配置,讓開(kāi)關(guān)決定走哪段代碼邏輯,如果領(lǐng)導(dǎo)哪天想變成亞馬遜云的服務(wù),繼續(xù)寫(xiě) if-else 就好了:

faceRecognition(Object faceImg){    if("AL".equals(configStr)){      //調(diào)用阿里云的人臉識(shí)別 API    }else if("TX".equals(configStr)){      //調(diào)用騰訊云的人臉識(shí)別 API    }else if("AM".equals(configStr)){      //調(diào)用亞馬遜云的人臉識(shí)別 API    }  }

不過(guò)還有一種更好的方法:

1. 定義一個(gè)接口:

interface FaceRecognitionInterface(){    faceRecognition(Object faceImg) ;  }

2. 多個(gè)實(shí)現(xiàn)類(lèi):

class ALFaceRecognition implements FaceRecognitionInterface{    //調(diào)用阿里云的人臉識(shí)別 API 的實(shí)現(xiàn)  }  class TXFaceRecognition implements FaceRecognitionInterface{    //調(diào)用騰訊云的人臉識(shí)別 API 的實(shí)現(xiàn)  }

3. 在調(diào)用人臉識(shí)別功能的代碼中:

String configStr = "讀取配置,走阿里云還是騰訊云";  FaceRecognitionInterface faceRe =  Class.forName(configStr).newInstance();  faceRe.faceRecognition(faceImg);

如果上面這個(gè)例子,你依然覺(jué)得在調(diào)用方法中做 if-else 判斷,和使用反射實(shí)現(xiàn)并沒(méi)有差太多,但是如果程序員 A 提供接口,程序員 B 提供實(shí)現(xiàn),程序員 C 寫(xiě)客戶(hù)端呢?

回憶一下 JDBC 的使用,比如創(chuàng)建一個(gè)連接:

public Connection getConnection() throws Exception{    Connection conn = null;    //初始化驅(qū)動(dòng)類(lèi)    Class.forName("com.mysql.jdbc.Driver");    conn = DriverManager.getConnection("jdbc:mysql://url","root", "admin");    return conn;  }

其中:

  •  程序員 A 提供接口:Oracle 公司(之前的 Sun)提供 JDBC 標(biāo)準(zhǔn)(接口)。

  •  程序員 B 提供實(shí)現(xiàn):各個(gè)數(shù)據(jù)庫(kù)廠商提供針對(duì)自家數(shù)據(jù)庫(kù)的實(shí)現(xiàn)。

  •  程序員 C 寫(xiě)客戶(hù)端:我等碼農(nóng)在 Java 中敲代碼訪問(wèn)數(shù)據(jù)庫(kù)。

總結(jié)一下Java 反射的作用:可以設(shè)計(jì)出更為通用和靈活的架構(gòu),很多框架為了保證其通用性,可以根據(jù)配置加載不用的類(lèi),這時(shí)候要用到反射。除此之外:

  •  動(dòng)態(tài)代理:在不改變目標(biāo)對(duì)象方法的情況下對(duì)方法進(jìn)行增強(qiáng),比如使用 AOP 攔截某些方法打印日志,這就需要通過(guò)反射執(zhí)行方法中的內(nèi)容。

  •  注解:利用反射機(jī)制,獲取注解并執(zhí)行對(duì)應(yīng)的行為。

05.用反射的用法

上文中我們知道了 Java 運(yùn)行期的源文件是 class 文件(字節(jié)碼),所以要使用反射,那么就需要獲取到字節(jié)碼文件對(duì)象,在 Java 中,獲取字節(jié)碼文件對(duì)象有三種方式:

  •  調(diào)用某個(gè)類(lèi)的 class 屬性:類(lèi)名.class

  •  調(diào)用對(duì)象的 getClass() 方法:對(duì)象.getClass()

  •  使用 Class 類(lèi)中的 forName() 靜態(tài)方法:Class.forName(類(lèi)的全路徑) ,建議使用這種方法

java.lang.reflect 類(lèi)庫(kù)提供了對(duì)反射的支持:

  •  Field :可以使用 get 和 set 方法讀取和修改對(duì)象的屬性;

  •  Method :可以使用 invoke() 方法調(diào)用對(duì)象中的方法;

  •  Constructor :可以用 newInstance() 創(chuàng)建新的對(duì)象。

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

優(yōu)點(diǎn):在運(yùn)行時(shí)動(dòng)態(tài)獲取類(lèi)和對(duì)象中的內(nèi)容,極大地提高系統(tǒng)的靈活性和擴(kuò)展性;夸張一些說(shuō),反射是框架設(shè)計(jì)的靈魂。

缺點(diǎn):會(huì)有一定的性能損耗,JVM 無(wú)法對(duì)這些代碼進(jìn)行優(yōu)化;破壞類(lèi)的封裝性。

總之,可能大家在平時(shí)的開(kāi)發(fā)過(guò)程中,感覺(jué)自己并沒(méi)有寫(xiě)過(guò)反射相關(guān)的代碼,但是在我們用到的各種開(kāi)源框架中,反射無(wú)處不在。

到此,關(guān)于“Java反射的作用是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向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