Java中反射機(jī)制和作用詳解
前言
很多剛學(xué)Java反射的同學(xué)可能對(duì)反射技術(shù)一頭霧水,為什么要學(xué)習(xí)反射,學(xué)習(xí)反射有什么作用,不用反射,通過new也能創(chuàng)建用戶對(duì)象。
那么接下來大師就帶你們了解一下反射是什么,為什么要學(xué)習(xí)反射?
下面我們首先通過一個(gè)實(shí)例來說明反射的好處:
方法1、不用反射技術(shù),創(chuàng)建用戶對(duì)象,調(diào)用sayHello方法
1.1 我們首先創(chuàng)建一個(gè)User類
package com.dashi; /** * Author:Java大師 * User對(duì)象,包含用戶的id和姓名以及sayHello方法 */ public class User { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String sayHello(String who) { return who+ "{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
1.2 創(chuàng)建測(cè)試用例
package com.dashi; import org.junit.Test; /** * 創(chuàng)建Juinit測(cè)試對(duì)象 */ public class Test01 { @Test public void test01(){ User user = new User(); user.setId(1); user.setName("Java大師"); //調(diào)用sayHello方法 System.out.println(user.sayHello("user1")); } }
1.3運(yùn)行結(jié)果如下,打印出sayHello結(jié)果:
user1{id=1, name='Java大師'} Process finished with exit code 0
方法2、通過反射技術(shù),創(chuàng)建用戶對(duì)象,調(diào)用sayHello方法
2.1 調(diào)用測(cè)試用例
@Test public void test02(){ try { //創(chuàng)建用戶對(duì)象字符串 String obj = "com.dashi.User"; //通過用戶對(duì)象字符串加載類 Class clz = Class.forName(obj); //通過newInstance方法,創(chuàng)建用戶對(duì)象 User user = (User)clz.newInstance(); user.setId(2); user.setName("Java大師2"); //調(diào)用sayHello方法 System.out.println(user.sayHello("user2")); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }
2.2 運(yùn)行結(jié)果如下,打印出sayHello結(jié)果:
user1{id=1, name='Java大師'}
user2{id=2, name='Java大師2'}Process finished with exit code 0
通過兩者以上對(duì)比,發(fā)現(xiàn)方法1和方法2都能創(chuàng)建用戶對(duì)象,并調(diào)用sayHello方法,并且打印的結(jié)果都正確。但是方法2比方法1先進(jìn)的地方是方法2針對(duì)字符串編程,方法1針對(duì)實(shí)體類編程。
那么針對(duì)字符串編程有什么好處呢,小伙伴們耐心接著往下看:
我們通過一個(gè)Dao層來演示下針對(duì)字符串編程的好處:
假設(shè)我們有一個(gè)IUserDao接口,里面有一個(gè)load方法,代碼如下:
package com.dashi; public interface IUserDao { public void load(); }
有兩個(gè)實(shí)現(xiàn)類來實(shí)現(xiàn)該IUserDao接口,實(shí)現(xiàn)類如下:
package com.dashi; /** * A實(shí)現(xiàn)類 */ public class AUserDao implements IUserDao{ @Override public void load() { System.out.println("這是AUserDao"); } } package com.dashi; /** * B實(shí)現(xiàn)類 */ public class BUserDao implements IUserDao{ @Override public void load() { System.out.println("這是BUserDao"); } }
方法3、不通過反射技術(shù),創(chuàng)建IUserDao,調(diào)用load方法
@Test public void testDao01(){ IUserDao userDao = new AUserDao(); userDao.load(); }
打印結(jié)果如下:
這是AUserDao
Process finished with exit code 0
方法4、通過反射技術(shù),創(chuàng)建IUserDao,調(diào)用load方法
@Test public void testDao02(){ try { //創(chuàng)建接口實(shí)現(xiàn)類字符串 String dao_str = "com.dashi.AUserDao"; //通過類加載的方式創(chuàng)建IUserDao IUserDao userDao = (IUserDao) Class.forName(dao_str).newInstance(); //調(diào)用load方法 userDao.load(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
打印結(jié)果如下:
這是AUserDao
這是AUserDaoProcess finished with exit code 0
通過類加載的方式,我們也創(chuàng)建了IUserDao對(duì)象,調(diào)用了load方法,和方法3的運(yùn)行結(jié)果一樣
方法5、通過反射技術(shù),創(chuàng)建IUserDao,調(diào)用load方法
@Test public void testDao03(){ try { //創(chuàng)建接口實(shí)現(xiàn)類字符串 String dao_str = "com.dashi.BUserDao"; //通過類加載的方式創(chuàng)建IUserDao Class clz = Class.forName(dao_str); IUserDao userDao= (IUserDao)clz.newInstance(); //創(chuàng)建調(diào)用方法字符串 String mm = "load"; //創(chuàng)建method對(duì)象 Method method = clz.getMethod(mm); //調(diào)用通過反射調(diào)用invoke方法 method.invoke(userDao); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
運(yùn)行結(jié)果如下:
這是AUserDao
這是AUserDao
這是BUserDaoProcess finished with exit code 0
通過method.invoke方法也可以實(shí)現(xiàn)load方法的調(diào)用
方法5比方法4和方法3更加靈活,不需要知道AUserDao和BUserDao實(shí)體類,只提供類的字符串和類的方法名稱,通過反射就可以實(shí)現(xiàn)方法的調(diào)用
實(shí)戰(zhàn)中的實(shí)際意義
假設(shè)我們的Dao層,從mysql遷移導(dǎo)oracle,SQL server等
運(yùn)用反射技術(shù),通過字符串編程,那么我們不需要進(jìn)行Dao層實(shí)體類的更改,只需要改動(dòng)我們的字符串名字就可以進(jìn)行Dao層的更新。比如:
1、不通過反射技術(shù),我們需要修改實(shí)現(xiàn)類中的AUserDao改為BUserDao IUserDao userDao = new AUserDao(); userDao.load(); ``如果有幾百個(gè)Dao,我們需要修改幾百次`` `` 2、運(yùn)用發(fā)射技術(shù)通過字符串編程,我們可以把字符串定義在properties文件中,通過修改properties文件中的配置即可實(shí)現(xiàn)Dao的更新 //創(chuàng)建接口實(shí)現(xiàn)類字符串 String dao_str = "com.dashi.AUserDao"; //可以改寫為:String dao_str = PropertyUtil.get("dao"); //通過類加載的方式創(chuàng)建IUserDao IUserDao userDao = (IUserDao) Class.forName(dao_str).newInstance(); //調(diào)用load方法 userDao.load();
這就是反射技術(shù)的實(shí)際運(yùn)用,通過以上實(shí)例就可以看出字符串編程和通過實(shí)現(xiàn)類編程的最大的區(qū)別和實(shí)際的意義
并且通過反射技術(shù)可以使我們的編程更加靈活
靈活運(yùn)用反射技術(shù),我們可以設(shè)計(jì)出更加靈活的框架哦~
總結(jié)
到此這篇關(guān)于Java中反射機(jī)制和作用詳解的文章就介紹到這了,更多相關(guān)Java反射機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot使用@Cacheable出現(xiàn)預(yù)覽工具亂碼的解決方法
直接使用注解進(jìn)行緩存數(shù)據(jù),我們?cè)偈褂霉ぞ呷ヮA(yù)覽存儲(chǔ)的數(shù)據(jù)時(shí)發(fā)現(xiàn)是亂碼,這是由于默認(rèn)序列化的問題,所以接下來將給大家介紹一下SpringBoot使用@Cacheable出現(xiàn)預(yù)覽工具亂碼的解決方法,需要的朋友可以參考下2023-10-10解決SpringBoot運(yùn)行Test時(shí)報(bào)錯(cuò):SpringBoot Unable to find
這篇文章主要介紹了SpringBoot運(yùn)行Test時(shí)報(bào)錯(cuò):SpringBoot Unable to find a @SpringBootConfiguration,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10Java 梳理總結(jié)關(guān)于static關(guān)鍵字常見問題
static關(guān)鍵字基本概念我們可以一句話來概括:方便在沒有創(chuàng)建對(duì)象的情況下來進(jìn)行調(diào)用。也就是說:被static關(guān)鍵字修飾的不需要?jiǎng)?chuàng)建對(duì)象去調(diào)用,直接根據(jù)類名就可以去訪問,讓我們來了解一下你可能還不知道情況2022-04-04懶人 IDEA 插件推薦: EasyCode 一鍵幫你生成所需代碼(Easycode用法)
這篇文章主要介紹了懶人 IDEA 插件推薦: EasyCode 一鍵幫你生成所需代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08SpringBoot與Quartz集成實(shí)現(xiàn)分布式定時(shí)任務(wù)集群的代碼實(shí)例
今天小編就為大家分享一篇關(guān)于SpringBoot與Quartz集成實(shí)現(xiàn)分布式定時(shí)任務(wù)集群的代碼實(shí)例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03springboot多數(shù)據(jù)源配合docker部署mysql主從實(shí)現(xiàn)讀寫分離效果
這篇文章主要介紹了springboot多數(shù)據(jù)源配合docker部署mysql主從實(shí)現(xiàn)讀寫分離,通過使用docker獲取mysql鏡像,具體內(nèi)容詳情跟隨小編一起看看吧2021-09-09Java?入門圖形用戶界面設(shè)計(jì)之事件處理下
圖形界面(簡(jiǎn)稱GUI)是指采用圖形方式顯示的計(jì)算機(jī)操作用戶界面。與早期計(jì)算機(jī)使用的命令行界面相比,圖形界面對(duì)于用戶來說在視覺上更易于接受,本篇精講Java語言中關(guān)于圖形用戶界面的事件處理2022-02-02