自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java反射:框架設(shè)計的靈魂

開發(fā) 后端
在學(xué)習(xí) Java 反射之前,先讓我們看看這幾個概念。希望能幫到你。

01.解釋型語言和編譯型語言

解釋型語言:不需要編譯,在運行的時候逐行翻譯解釋;修改代碼時可以直接修改,可以快速部署,不過性能上會比編譯型語言稍差;比如 JavaScript、Python ;

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

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

02.動態(tài)語言和靜態(tài)語言

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

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

03.反射的概念

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

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

在 Java 中,要使用一個類中的某個方法,“正向”都是這樣的: 

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

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

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

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

04.反射的作用

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

當(dāng)然可以!不過很多場景中,在代碼運行之前并不知道需要使用哪個類,或者說在運行的時候才決定使用哪個類;

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

 

  1. faceRecognition(Object faceImg){  
  2.   //調(diào)用阿里云的人臉識別 API 

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

 

  1. faceRecognition(Object faceImg){  
  2.   //調(diào)用騰訊云的人臉識別 API  

修改上線運行了兩個月,領(lǐng)導(dǎo)說:“換回來吧”...  ...

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

  1. faceRecognition(Object faceImg){  
  2.   if("AL".equals(configStr)){  
  3.     //調(diào)用阿里云的人臉識別 API  
  4.   }else if("TX".equals(configStr)){  
  5.     //調(diào)用騰訊云的人臉識別 API  
  6.   }else if("AM".equals(configStr)){  
  7.     //調(diào)用亞馬遜云的人臉識別 API  
  8.   }  

不過還有一種更好的方法:

1. 定義一個接口: 

  1. interface FaceRecognitionInterface(){  
  2.   faceRecognition(Object faceImg) ;  

2. 多個實現(xiàn)類: 

  1. class ALFaceRecognition implements FaceRecognitionInterface{  
  2.   //調(diào)用阿里云的人臉識別 API 的實現(xiàn)  
  3.  
  4. class TXFaceRecognition implements FaceRecognitionInterface{  
  5.   //調(diào)用騰訊云的人臉識別 API 的實現(xiàn)  

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

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

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

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

  1. public Connection getConnection() throws Exception{  
  2.   Connection conn = null 
  3.   //初始化驅(qū)動類  
  4.   Class.forName("com.mysql.jdbc.Driver");  
  5.   conn = DriverManager.getConnection("jdbc:mysql://url","root", "admin");  
  6.   return conn;  

其中:

  •  程序員 A 提供接口:Oracle 公司(之前的 Sun)提供 JDBC 標(biāo)準(zhǔn)(接口)。
  •  程序員 B 提供實現(xiàn):各個數(shù)據(jù)庫廠商提供針對自家數(shù)據(jù)庫的實現(xiàn)。
  •  程序員 C 寫客戶端:我等碼農(nóng)在 Java 中敲代碼訪問數(shù)據(jù)庫。

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

  •  動態(tài)代理:在不改變目標(biāo)對象方法的情況下對方法進行增強,比如使用 AOP 攔截某些方法打印日志,這就需要通過反射執(zhí)行方法中的內(nèi)容。
  •  注解:利用反射機制,獲取注解并執(zhí)行對應(yīng)的行為。

05.用反射的用法

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

  •  調(diào)用某個類的 class 屬性:類名.class
  •  調(diào)用對象的 getClass() 方法:對象.getClass()
  •  使用 Class 類中的 forName() 靜態(tài)方法:Class.forName(類的全路徑) ,建議使用這種方法

java.lang.reflect 類庫提供了對反射的支持:

  •  Field :可以使用 get 和 set 方法讀取和修改對象的屬性;
  •  Method :可以使用 invoke() 方法調(diào)用對象中的方法;
  •  Constructor :可以用 newInstance() 創(chuàng)建新的對象。

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

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

缺點:會有一定的性能損耗,JVM 無法對這些代碼進行優(yōu)化;破壞類的封裝性。

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

 

責(zé)任編輯:龐桂玉 來源: Java編程
相關(guān)推薦

2021-02-23 08:18:04

Java 反射機制

2012-06-25 12:43:26

.NET框架

2012-01-18 10:20:42

框架設(shè)計

2012-06-25 09:28:42

.NET可逆框架

2016-03-23 11:05:58

Socket開發(fā)框架分析

2009-09-08 09:12:12

LINQ構(gòu)建框架設(shè)計

2022-06-15 11:01:59

自定義SPIJava

2011-04-22 09:26:57

MVC設(shè)計

2022-09-15 18:32:13

SPI模型框架

2010-09-25 13:09:39

UISymbian

2012-01-10 10:04:43

Node.js

2022-04-03 15:44:55

Vue.js框架設(shè)計設(shè)計與實現(xiàn)

2022-10-10 09:11:12

互聯(lián)網(wǎng)存儲系統(tǒng)云計算

2013-09-09 10:48:24

iOS無線客戶端框架設(shè)計

2013-09-03 09:35:48

無線客戶端框架設(shè)計iOS

2013-09-03 09:55:42

iOS無線客戶端框架設(shè)計

2022-09-25 21:45:54

日志平臺

2017-04-12 23:33:38

DevOps平衡計分卡框架

2024-01-31 22:08:18

分布式重試框架

2023-10-26 09:02:30

框架設(shè)計模式
點贊
收藏

51CTO技術(shù)棧公眾號