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

全面了解Java反射機(jī)制

 更新時(shí)間:2020年03月26日 08:53:35   作者:程序新視界  
Java的反射機(jī)制在實(shí)踐中可謂無處不在,如果你已經(jīng)工作幾年,還對(duì)Java的反射機(jī)制一知半解,那么這篇文章絕對(duì)值得你讀一讀。

什么是反射

反射 (Reflection) 是Java的特征之一,它允許運(yùn)行中的Java程序獲取自身的信息,并且可以操作類或?qū)ο蟮膬?nèi)部屬性。

通俗的來講就是:通過反射機(jī)制,可以在運(yùn)行時(shí)獲得程序或程序集中每一個(gè)類型的成員和成員的信息。

注意這里的重點(diǎn)是:運(yùn)行時(shí),而不是編譯時(shí)。我們常規(guī)情況下寫的對(duì)象類型都是在編譯期就確定下來的。而Java反射機(jī)制可以動(dòng)態(tài)地創(chuàng)建對(duì)象并調(diào)用其屬性,這樣創(chuàng)建對(duì)象的方式便異常靈活了。

雖然通過反射可以動(dòng)態(tài)的創(chuàng)建對(duì)象,增加了靈活性,但也不是什么地方都可用,還要考慮性能、編碼量、安全、面向?qū)ο笮缘取?/p>

我們知道Java是面向?qū)ο蟮?,如果通過反射機(jī)制去操作對(duì)象里面的屬性或方法,一定程度上破壞了面向?qū)ο蟮奶匦?。同時(shí),通過反射機(jī)制還可以修改私有變量,也存在一定的安全性問題。

但這并不影響反射在實(shí)踐中的應(yīng)用,幾乎各大框架多多少少都在使用Java反射機(jī)制。特別是主流的Spring框架。

功能及用途

Java反射主要提供以下功能:

在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類;
在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象;
在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法(通過反射甚至可以調(diào)用private方法);
在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法

反射最重要的用途之一就是開發(fā)各類通用框架。以Spring為例,當(dāng)基于XML進(jìn)行配置Bean時(shí),我們通常寫如下代碼:

<bean class="com.choupangxia.UserServiceImpl">
</bean>

Spring在啟動(dòng)的時(shí)候便會(huì)利用反射機(jī)制去加載對(duì)應(yīng)的UserServiceImpl類,然后進(jìn)行實(shí)例化。如果不存在該類則會(huì)拋出異常,通常異常中還會(huì)出現(xiàn)invoke方法調(diào)用的堆棧信息。

當(dāng)Spring基于注解去實(shí)例化對(duì)象時(shí),同樣利用的是反射機(jī)制。下面通過一個(gè)簡(jiǎn)單demo示例,演示一下如何通過反射獲得注解信息:

static void initUser(User user) throws IllegalAccessException {

 // 獲取User類中所有的屬性(getFields無法獲得private屬性)
 Field[] fields = User.class.getDeclaredFields();

 // 遍歷所有屬性
 for (Field field : fields) {
  // 如果屬性上有此注解,則進(jìn)行賦值操作
  if (field.isAnnotationPresent(InitSex.class)) {
   InitSex init = field.getAnnotation(InitSex.class);
   field.setAccessible(true);
   // 設(shè)置屬性的性別值
   field.set(user, init.sex().toString());
   System.out.println("完成屬性值的修改,修改值為:" + init.sex().toString());
  }
 }
}

更多關(guān)于Java反射的例子我們就不多說了。上面的示例現(xiàn)在看不懂也沒關(guān)系,下面我們就來詳細(xì)介紹一下Java反射機(jī)制的具體使用。

簡(jiǎn)單示例

我們通過一個(gè)簡(jiǎn)單的示例對(duì)比,來了解一下Java反射機(jī)制。首先來看正常情況下創(chuàng)建對(duì)象并使用對(duì)象的示例:

User user = new User();
user.setUsername("公眾號(hào):程序新視界");
user.setAge(3);

那么,當(dāng)基于反射機(jī)制來達(dá)到統(tǒng)一效果該怎么做呢?看下面的具體實(shí)現(xiàn):

@Test
public void testCreateReflect() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
  InvocationTargetException, InstantiationException {
 // 獲取User所對(duì)應(yīng)的Class對(duì)象
 Class clz = Class.forName("com.choupangxia.reflect.User");
 // 獲取User類無參數(shù)的構(gòu)造器
 Constructor constructor = clz.getConstructor();
 // 通過構(gòu)造器創(chuàng)建User對(duì)象
 User user = (User) constructor.newInstance();
 user.setUsername("公眾號(hào):程序新視界");
 user.setAge(3);
 System.out.println("username=" + user.getUsername());
 System.out.println("age=" + user.getAge());
}

在上述過程中通過Class.forName獲得User所對(duì)應(yīng)的Class對(duì)象,獲得構(gòu)造器Constructor,通過構(gòu)造器創(chuàng)建出來一個(gè)User對(duì)象,然后調(diào)用對(duì)應(yīng)的方法。

當(dāng)然,后面的步驟中也可以完全不出現(xiàn)User類,直接通過Class對(duì)象獲得對(duì)應(yīng)的Method進(jìn)行調(diào)用。示例如下:

Method setUsernameMethod = clz.getMethod("setUsername", String.class);
Method setAgeMethod = clz.getMethod("setAge", int.class);

setUsernameMethod.invoke(obj,"公眾號(hào):程序新視界");
setAgeMethod.invoke(obj,3);

關(guān)于get方法也是如此操作,就不再贅述。

經(jīng)過上面的實(shí)例我們已經(jīng)能夠正常創(chuàng)建對(duì)象,并使用對(duì)象了。下面就看看反射常用的API,通過這些API我們可以實(shí)現(xiàn)更多的更復(fù)雜的功能。

反射常用API

獲取Class對(duì)象的三種方法

第一種方法:當(dāng)你知道類的全路徑名時(shí),可使用Class.forName靜態(tài)方法來獲得Class對(duì)象。上面的示例就是通過這種方法獲得:

Class clz = Class.forName("com.choupangxia.reflect.User");

第二種方法:通過“.class”獲得。前提條件是在編譯前就能夠拿到對(duì)應(yīng)的類。

Class clz = User.class;

第三種:使用類對(duì)象的getClass()方法。

User user = new User();
Class clz = user.getClass();

創(chuàng)建對(duì)象的兩種方法

可以通過Class對(duì)象的newInstance()方法和通過Constructor 對(duì)象的newInstance()方法創(chuàng)建類的實(shí)例對(duì)象。

第一種:通過Class對(duì)象的newInstance()方法。

Class clz = User.class;
User user = (User) clz.newInstance();

第二種:通過Constructor對(duì)象的newInstance()方法。

Class clz = Class.forName("com.choupangxia.reflect.User");
Constructor constructor = clz.getConstructor();
User user = (User) constructor.newInstance();

其中第二種方法創(chuàng)建類對(duì)象可以選擇特定構(gòu)造方法,而通過 Class對(duì)象則只能使用默認(rèn)的無參數(shù)構(gòu)造方法。

Class clz = User.class;
Constructor constructor = clz.getConstructor(String.class);
User user = (User) constructor.newInstance("公眾號(hào):程序新視界");

獲取類屬性、方法、構(gòu)造器
通過Class對(duì)象的getFields()方法獲取非私有屬性。

Field[] fields = clz.getFields();
for(Field field : fields){
 System.out.println(field.getName());
}

上述實(shí)例中的User對(duì)象屬性都是private,無法直接通過上述方法獲取,可將其中一個(gè)屬性改為public,即可獲取。

通過Class對(duì)象的getDeclaredFields()方法獲取所有屬性。

Field[] fields = clz.getDeclaredFields();
for(Field field : fields){
 System.out.println(field.getName());
}

執(zhí)行打印結(jié)果:

username
age

當(dāng)然針對(duì)屬性的其他值也是可以獲取的,針對(duì)私有屬性的修改需要先調(diào)用field.setAccessible(true)方法,然后再進(jìn)行賦值。關(guān)于具體應(yīng)用,回頭看我們最開始關(guān)于注解的實(shí)例中的使用。

獲取方法的示例如下:

Method[] methods = clz.getMethods();
for(Method method : methods){
 System.out.println(method.getName());
}

打印結(jié)果:

setUsername
setAge
getUsername
getAge
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

可以看到,不僅獲取到了當(dāng)前類的方法,還獲取到了該類父類Object類中定義的方法。

關(guān)于獲取構(gòu)造器的方法上面已經(jīng)講到了,就不再贅述。而上述的這些方法在Class中都有相應(yīng)的重載的方法,可根據(jù)具體情況進(jìn)行靈活使用。

利用反射創(chuàng)建數(shù)組

最后,我們?cè)倏匆粋€(gè)通過反射創(chuàng)建數(shù)組的實(shí)例。

@Test
public void createArray() throws ClassNotFoundException {
 Class<?> cls = Class.forName("java.lang.String");
 Object array = Array.newInstance(cls,5);
 // 向數(shù)組添加內(nèi)容
 Array.set(array,0,"Hello");
 Array.set(array,1,"公眾號(hào)");
 Array.set(array,2,"程序新視界");
 Array.set(array,3,"二師兄");
 Array.set(array,4,"Java");
 // 獲取數(shù)組中指定位置的內(nèi)容
 System.out.println(Array.get(array,2));
}

小結(jié)

想必經(jīng)過上述的學(xué)習(xí),對(duì)Java反射機(jī)制有了更進(jìn)一步的了解,在最開始我們已經(jīng)說了反射機(jī)制也是有不足的。因此,如果可能盡量使用正統(tǒng)的寫法,但如果你在開發(fā)通用框架,則可考慮使用。

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

相關(guān)文章

  • Java中.divide()方法使用及注意事項(xiàng)詳解

    Java中.divide()方法使用及注意事項(xiàng)詳解

    divide方法就是bigdecimal類中的一個(gè)除法計(jì)算方法,由于該divide方法參數(shù)類型眾多并且不易理解容易出現(xiàn)錯(cuò)誤,這篇文章主要給大家介紹了關(guān)于Java中.divide()方法使用及注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • SpringBoot Admin用法實(shí)例講解

    SpringBoot Admin用法實(shí)例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于SpringBoot Admin用法實(shí)例內(nèi)容,有需要的朋友們可以參考學(xué)習(xí)下。
    2019-10-10
  • Java調(diào)用騰訊云短信API接口的實(shí)現(xiàn)

    Java調(diào)用騰訊云短信API接口的實(shí)現(xiàn)

    這篇文章主要介紹了Java調(diào)用騰訊云短信API接口的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • SpringBoot中@Pattern注解對(duì)時(shí)間格式校驗(yàn)方式

    SpringBoot中@Pattern注解對(duì)時(shí)間格式校驗(yàn)方式

    這篇文章主要介紹了SpringBoot中@Pattern注解對(duì)時(shí)間格式校驗(yàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • springboot整合quartz實(shí)現(xiàn)定時(shí)任務(wù)示例

    springboot整合quartz實(shí)現(xiàn)定時(shí)任務(wù)示例

    spring支持多種定時(shí)任務(wù)的實(shí)現(xiàn)。我們來介紹下使用spring的定時(shí)器和使用quartz定時(shí)器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • mybatis批量新增、刪除、查詢和修改方式

    mybatis批量新增、刪除、查詢和修改方式

    這篇文章主要介紹了mybatis批量新增、刪除、查詢和修改方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • IDEA 中創(chuàng)建SpringBoot 父子模塊的實(shí)現(xiàn)

    IDEA 中創(chuàng)建SpringBoot 父子模塊的實(shí)現(xiàn)

    這篇文章主要介紹了IDEA 中創(chuàng)建SpringBoot 父子模塊的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Java中的構(gòu)造方法this、super的用法詳解

    Java中的構(gòu)造方法this、super的用法詳解

    這篇文章較詳細(xì)的給大家介紹了Java中的構(gòu)造方法this、super的用法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-07-07
  • springboot加載配值文件的實(shí)現(xiàn)步驟

    springboot加載配值文件的實(shí)現(xiàn)步驟

    本文主要介紹了springboot加載配值文件的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • 詳解Spring Boot對(duì) Apache Pulsar的支持

    詳解Spring Boot對(duì) Apache Pulsar的支持

    Spring Boot通過提供spring-pulsar和spring-pulsar-reactive自動(dòng)配置支持Apache Pulsar,類路徑中這些依賴存在時(shí),Spring Boot自動(dòng)配置命令式和反應(yīng)式Pulsar組件,PulsarClient自動(dòng)注冊(cè),默認(rèn)連接本地Pulsar實(shí)例,感興趣的朋友一起看看吧
    2024-11-11

最新評(píng)論

五华县| 如东县| 盐山县| 开封县| 鹤岗市| 鄯善县| 枞阳县| 凉山| 铜梁县| 赣榆县| 筠连县| 佳木斯市| 无为县| 治多县| 徐汇区| 会东县| 平阳县| 甘泉县| 肥城市| 班戈县| 赣州市| 威宁| 吉安市| 伽师县| 呼伦贝尔市| 马公市| 景德镇市| 德钦县| 郯城县| 麟游县| 承德市| 招远市| 清新县| 定州市| 沁阳市| 且末县| 丹凤县| 察隅县| 出国| 乌审旗| 阿尔山市|