成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

JAVA中的糕富帥技術(shù)——反射(一)

瀏覽:6日期:2022-09-06 16:13:03

 今天就來談?wù)劮瓷錂C(jī)制;學(xué)過JAVA的人不一定懂得反射,但是一定聽說過反射,不過也僅僅是聽說過而已;因為反射用的地方也不會那么多,但是反射用的妙經(jīng)常會解決我們撓破頭皮的大問題。至于諸如為什么叫做反射、而不叫做正射倒射此類的歷史問題,還是交給歷史學(xué)家去研究吧。。。

反射的基石

在談反射之前,我們應(yīng)該先了解下類的概念來引入。類是一種抽象的概念,舉個例子“我爸是李剛我爸李雙江”,從這句話中我們發(fā)現(xiàn)有李剛、李雙江這兩個人,我們來抽象它們的特點,我們發(fā)現(xiàn)它們都像人。沒錯,那么我們就可以將人作為它們的一個抽象,反過來說李剛和李雙江就是人的一個具體實例;所以我們可以用一個Person類代表人來表示這種抽象。既然理解了類的概念,那些年那些陪我們度過日日夜夜的java類們,我們是不是也應(yīng)該抽象出一個類來證明一下他們,沒錯,那就是Class了!

Class就是java類的抽象,它抽象出了java的共性,如類的名字、類的構(gòu)造方法、類的成員變量、類的老爸、類的方法等等等。既然這么說,那么我們通過這個Class,我們就可以得到這個類的方方面面的信息、興許還能比查戶口還詳細(xì)呢。我們創(chuàng)建出的每一個類,例如person類,說到底也就是我們實例化了一個Class的實例,來保存person類的名字、變量、方法這些信息,在內(nèi)存中表示就是保存了person類的字節(jié)碼,如果你理解了這些并且接受了我的看法,那么咱們有共同語言,可以繼續(xù)往下說。

既然person類有擁有自己的字節(jié)碼,那么我們可以獲取到這個字節(jié)碼嗎?答案是肯定的,而且還不止一種方法。參見代碼:

public static void main(String[] args) throws Exception {//第一種方法,直接通過Person類來獲取字節(jié)碼 Class cls1 = Person.class;//第二種方法,通過類的實例來獲取Person類的字節(jié)碼 Person person = new Person();Class cls2 = person.getClass();//第三種方法,調(diào)用Class類的靜態(tài)方法來獲取對應(yīng)類的字節(jié)碼,該方法會拋出異常 Class cls3 = Class.forName('Person');}

從代碼中看,我們可以斷定:Person類的字節(jié)碼就是Class的具體實例;我們也可以猜到,至于類的字節(jié)碼有包含什么東東,大家盡管猜吧,后面我會慢慢講解。我們再來看看下面的代碼:

System.out.println(cls1 == cls2);System.out.println(cls2 == cls3);

我們運行程序,會發(fā)現(xiàn)輸出了:

truetrue

這三個玩意竟然是同一個東西,那么就很好解釋了:在java的虛擬機(jī)中,每一個類都會被保存成為一個字節(jié)碼,用來保存該類的信息如名字、父類、變量、方法等。一個類的字節(jié)碼在虛擬機(jī)中有且只有一個,也就是在第一次加載該類的時候會將類的字節(jié)碼加載到j(luò)ava虛擬機(jī)中,而上面有三種方法可以從虛擬機(jī)中獲取類的字節(jié)碼(PS:第三種方法最為常用),但是你別疑惑獲取這個字節(jié)碼干嘛嘛用,我們要反射嘛,說白了我們就是要來強(qiáng)暴這字節(jié)碼(Class)。。。。。(~ o ~)~zZ

理解反射

既然前面講解了Class類,現(xiàn)在我們可以開始講反射了。反射是什么呢?反射就是將類的各種成分映射成各種類,我們知道一個java類可以用一個class的對象來表示,這個類的組成成分有名字、變量、構(gòu)造方法等信息,我們當(dāng)然可以用一個個java類的表示。換句話說,表示java類的Class類提供了一系列的方法給我們用來獲取其中的變量、方法、構(gòu)造方法等信息,這些信息也有相應(yīng)的類的實例來表示,也就是Field、Method、Constructor等等?;蛘吒ㄋ椎恼f,F(xiàn)ield就是java類中的所有變量的抽象、同理Method就是java類中所有方法的抽象,如果還是看不懂,很正常,往下看代碼估計更好理解。

構(gòu)造方法的反射

從前面我們知道,Constructor就是java類所有構(gòu)造方法的抽象。那么我們怎么通過反射來獲取類的構(gòu)造方法呢,參見代碼:

public class Test{ public static void main(String[] args) throws Exception {Class cls = Person.class;//獲取Person類的字節(jié)碼 Constructor constructor1 = cls.getConstructor();//調(diào)用getConstructor()獲取Person無參構(gòu)造方法 Person p1 = (Person) constructor1.newInstance();//通過調(diào)用newInstance()來執(zhí)行無參構(gòu)造方法 Constructor constructor2 = cls.getConstructor(int.class);//調(diào)用getConstructor(*.class)獲取Person帶參構(gòu)造方法 Person p2 = (Person) constructor2.newInstance(1);//通過調(diào)用newInstance(int)來執(zhí)行帶參構(gòu)造方法 }} class Person{ public Person(){System.out.println('無參構(gòu)造方法');} public Person(int i){System.out.println('帶參構(gòu)造方法');}}

控制臺輸出:

無參構(gòu)造方法帶參構(gòu)造方法

這里我們開始講解一下,代碼通過Person.class來獲取Person類的字節(jié)碼并將其保存在一個Class類的實例cls中,然后再通過cls.getConstructor()來獲取字節(jié)碼中的構(gòu)造方法并將其放入Constructor的實例constructor之中,很明顯,這個constructor并不是Person的構(gòu)造方法,而是保存Person構(gòu)造方法的一個實例,所以我們可以通過調(diào)用newInstance()來獲取保存在constructor中的person類的構(gòu)造方法并執(zhí)行,構(gòu)造方法執(zhí)行并返回一個Object的實例,并將其強(qiáng)轉(zhuǎn)為Person并保存在person的變量中,這就是調(diào)用反射來獲取構(gòu)造方法生成實例的全過程。

在代碼中,我們也可以知道怎么獲取帶參的構(gòu)造方法,這是我們需要在getConstructor()是傳入構(gòu)造方法對應(yīng)參數(shù)的字節(jié)碼,例如代碼中Person(int i)我們需要傳入一個int.class(或者是Integet.TYPE)的字節(jié)碼提供給Class定位需要獲取的構(gòu)造方法。但是如果你比較貪心想獲取全部的構(gòu)造方法,沒問題,通過getConstructors():

Class cls = Person.class;//獲取Person類的字節(jié)碼 Constructor[] constructors = cls.getConstructors();//調(diào)用getConstructor()獲取Person無參構(gòu)造方法 for(Constructor c : constructors){//Person p = c.newInstance(****);遍歷執(zhí)行構(gòu)造方法 }

然后通過for循環(huán),就可以處理你所需要的構(gòu)造方法了。

成員變量的反射

我們說完了構(gòu)造方法的反射,我們就接下來談?wù)劤蓡T變量的反射的用法。慣例還是先看代碼:

public class Test{ public static void main(String[] args) throws Exception {Person p = new Person('小紅', 20);Class cls = Class.forName('com.net168.test.Person');Field fieldName = cls.getField('name'); //fieldNmae的值是小紅嗎?錯!它只是代表Person類身上name的這個變量,并沒有對應(yīng)到對象身上 // System.out.println(fieldNmae); //fieldNmae不代表具體的值,只代表一個變量,所以我們需要傳入一個person實例才能獲取到其對應(yīng)的值 System.out.println(fieldName.get(p)); }} class Person{ public Person(String name, int age){ this.name = name; this.age = age; } public String name; private int age;//對于某些人來說,年齡是秘密! }

跟構(gòu)造方法的反射的實現(xiàn)差不多,我們也是先通過獲取Person的字節(jié)碼cls,然后從其中將Person的成員變量映射成一個Field類,在這里我們將Person.name這個變量映射成fieldName這個對象,當(dāng)然我們不可能單純的從fieldName這個對象中獲取咱們的“小紅”,因為fieldName是從cls中獲取的而并不是從person的實例中獲取的,所以它值并不是小紅;而是我們可以通過小紅這個person的實例p與fieldName聯(lián)系起來,也就是調(diào)用fieldName.get(p)才能獲取小紅這個字符串。

但是我們?nèi)绻氆@取小紅年齡呢,女人的年齡大多是秘密,私有變量我們也可以這樣獲取嗎?修改下代碼:

Person p = new Person('小紅', 20);Class cls = Class.forName('com.net168.test.Person');Field fieldAge = cls.getField('age');System.out.println(fieldAge.get(p));

執(zhí)行結(jié)果是:

Exception in thread 'main' java.lang.NoSuchFieldException: ageat java.lang.Class.getField(Unknown Source)at com.net168.test.Test.main(Test.java:11)

沒有這個字段,明明是有這個age的字段呀!但是我們發(fā)現(xiàn),原來這個女生的年齡是私有的,她就是不肯告訴咱們啊,那怎么辦?她不想告訴我們,我們就沒法知道了嗎?屌絲是不會那么容易屈服的!所以我們可以稍作一點處理,如下:

Person p = new Person('小紅', 20);Class cls = Class.forName('com.net168.test.Person');Field fieldAge = cls.getDeclaredField('age');//獲取類的私有變量 fieldAge.setAccessible(true);//設(shè)置該私有變量可被外面訪問 System.out.println(fieldAge.get(p));

可以通過getDeclaredField()來獲取Person類的私有變量,而且我們還可以在獲取到外界看不到的私有變量后,再通過setAccessible(true)設(shè)置該私有變量可以被強(qiáng)制訪問。暴力吧,JAVA的反射也被有些人叫做暴力反射。。。運行代碼,我們就知道了小紅的芳齡 了:20

成員方法的反射

如果大家看懂了前面成員變量和構(gòu)造方法的反射,基本上再了解成員方法的反射就沒有什么困難了,不賣關(guān)子,還是先上下代碼:

public class Test{ public static void main(String[] args) throws Exception {Person p = new Person();Class cls = p.getClass();//獲取Person的字節(jié)碼 //獲取setName()方法,需要傳入?yún)?shù)為String Method method1 = cls.getMethod('setName', String.class);method1.invoke(p, '小明');//關(guān)聯(lián)p,輸入“小明”并執(zhí)行該方法 //獲取getName()方法,無參則設(shè)為null Method method2 = cls.getMethod('getName', null);String name = (String) method2.invoke(p, null);//invoke返回的類型為Object System.out.println(name); //獲取靜態(tài)方法,由于靜態(tài)方法只依賴與類,所以不需要提供具體的實例 Method method3 = cls.getMethod('show', int.class); // method3.invoke(p, 1);提供具體實例p也可通過編譯 method3.invoke(null, 1); }} class Person{ public String name; public String getName(){ return name; } public void setName(String name){ this.name = name;System.out.println('設(shè)置name值為:' + name); } public static void show(int i){System.out.println('這是一個靜態(tài)方法:' + i); }}

程序運行結(jié)果:

設(shè)置name值為:小明小明這是一個靜態(tài)方法:1

在方法的反射中,我們是利用了Method這個類,由于跟構(gòu)造方法類似,所以我不就再就獲取有參無參的方法的不同之處進(jìn)行講解。總體來說,就是通過Person的字節(jié)碼獲取到Person類中對應(yīng)的方法并將其保存到Method的一個對象中,然后通過這個對象跟Person的具體實例進(jìn)行搭配,通過invoke()就可以調(diào)用到具體實例的對應(yīng)方法。在這里我們需要注意的時靜態(tài)方法的反射,由于靜態(tài)方法屬于一個類并不是屬于特定的一個對象,所以我們在調(diào)用靜態(tài)方法的invoke()時,并不需要傳入一個對象,當(dāng)然你非要傳入一個具體的實例也是沒有關(guān)系的,答案依然正確。

標(biāo)簽: Java
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
国产精品福利一区| 在线日韩中文| 成人妖精视频yjsp地址| 久久久久久9| 亚洲国产cao| 最新国产乱人伦偷精品免费网站| 久久久午夜电影| 波多野结衣视频一区| 91精品国产麻豆国产自产在线 | 亚洲成人av一区二区三区| 亚洲大胆视频| 2020国产精品久久精品美国| 国产91精品久久久久久久网曝门| 欧美精品一卡两卡| 国产最新精品精品你懂的| 欧美天堂一区二区三区| 日本女人一区二区三区| 91久久精品一区二区| 蜜臀av一区二区在线免费观看| 色婷婷av一区二区三区gif| 视频一区视频二区在线观看| 葵司免费一区二区三区四区五区| 亚洲国产精品影院| 久久综合影视| 极品尤物av久久免费看| 91麻豆精品国产91久久久久久 | 国产一区再线| 中文字幕亚洲一区二区av在线| 一区免费在线| 一区二区欧美国产| 国产精品五区| 性久久久久久久久| 91精品91久久久中77777| 激情综合色播五月| 日韩欧美亚洲国产另类| 99re在线视频这里只有精品| 欧美激情一区二区三区全黄| 国产一区视频在线观看免费| 亚洲精品日日夜夜| 久久久综合香蕉尹人综合网| 精品一区免费av| 精品少妇一区二区| 国产真实久久| 亚洲第一激情av| 欧美日韩亚洲综合一区二区三区| 国产v日产∨综合v精品视频| xvideos.蜜桃一区二区| 亚洲午夜激情| 污片在线观看一区二区| 欧美美女激情18p| av亚洲精华国产精华精华| 国产精品狼人久久影院观看方式| 亚洲久久视频| 日韩精品成人一区二区三区| 在线电影一区二区三区| 91在线视频网址| 伊人夜夜躁av伊人久久| 久久精品主播| 国产91精品一区二区麻豆网站| 国产调教视频一区| 国产精品区一区| 激情综合网激情| 国产欧美日本一区二区三区| 一区二区欧美日韩| 免费看日韩精品| 欧美成人精精品一区二区频| 午夜精品短视频| 亚洲一区二区三区爽爽爽爽爽| 欧洲av一区二区嗯嗯嗯啊| 成人精品免费视频| 亚洲人成伊人成综合网小说| 久久亚洲精选| 大白屁股一区二区视频| 亚洲视频一区二区在线| 在线免费精品视频| 91色porny| 日韩专区欧美专区| 欧美tk—视频vk| 一区二区免费在线视频| 国内偷窥港台综合视频在线播放| 日本一区二区三区电影| 一本大道久久a久久精品综合| 成人小视频免费在线观看| 樱桃国产成人精品视频| 欧美日韩国产美| 好看的av在线不卡观看| 蜜桃久久精品一区二区| 久久久www成人免费无遮挡大片| 免费国产自线拍一欧美视频| 成人黄色国产精品网站大全在线免费观看 | 97aⅴ精品视频一二三区| 亚洲一区二区三区在线| 91精品久久久久久蜜臀| 亚洲国产日韩综合一区| 精彩视频一区二区| 自拍偷自拍亚洲精品播放| 欧美丰满美乳xxx高潮www| 在线观看的日韩av| 国产成人免费在线观看| 亚洲国产美国国产综合一区二区| 精品国精品国产| 色8久久人人97超碰香蕉987| 欧美日韩在线精品| 狠狠v欧美v日韩v亚洲ⅴ| 亚洲三级在线看| 日韩欧美黄色影院| 媚黑女一区二区| 色综合色综合色综合| 秋霞影院一区二区| 国产精品国产三级国产a| 欧美精品在线视频| 欧美一级网站| 欧美三级乱码| 国产成人在线免费| 五月激情综合婷婷| 国产欧美日韩视频在线观看| 欧美日韩国产在线观看| 国产欧美日韩亚洲一区二区三区| 成人激情动漫在线观看| 日韩国产欧美在线观看| 国产精品久久夜| 日韩视频一区在线观看| 日本精品视频一区二区三区| 亚洲小说欧美另类社区| 国产不卡视频一区| 蜜臀av性久久久久av蜜臀妖精| 自拍视频在线观看一区二区| 日韩精品一区二区三区在线观看| 色综合久久99| 亚洲精品中文字幕在线| 97se亚洲国产综合在线| 国产中文字幕精品| 日韩精品久久久久久| 亚洲精品第1页| 国产欧美一区视频| 在线播放91灌醉迷j高跟美女| 午夜亚洲性色视频| 狠狠久久婷婷| 欧美.www| av高清久久久| 国内欧美视频一区二区| 三级久久三级久久| 亚洲男人的天堂在线观看| 欧美国产日韩精品免费观看| 日韩欧美国产一区在线观看| 欧美日韩一区小说| 色噜噜狠狠成人中文综合| 亚洲精品欧洲精品| 国内外成人免费视频| 99久久综合色| 亚洲国产成人自拍| 精品久久久久久久久久久久包黑料| 欧美日韩国产免费| 在线观看亚洲一区| 玖玖在线精品| 午夜综合激情| 国产精品永久入口久久久| 韩日欧美一区| 狠狠干成人综合网| 欧美99在线视频观看| 成人深夜视频在线观看| 国产麻豆欧美日韩一区| 韩国av一区二区| 狠狠色狠狠色合久久伊人| 麻豆成人在线观看| 久久精品国产精品青草| 青青草一区二区三区| 琪琪久久久久日韩精品| 七七婷婷婷婷精品国产| 青青草原综合久久大伊人精品优势| 亚洲一区二区美女| 一区二区三区免费看视频| 一区二区视频在线| 亚洲综合色成人| 性欧美疯狂xxxxbbbb| 香蕉加勒比综合久久| 天天影视色香欲综合网老头| 天天综合网 天天综合色| 日本欧美韩国一区三区| 麻豆国产一区二区| 精品在线观看免费| 国产盗摄女厕一区二区三区 | 国内成人精品2018免费看| 久久91精品久久久久久秒播| 久久精品国产免费看久久精品| 精品亚洲成a人| 国产福利电影一区二区三区| 黄色精品一二区| 国产suv一区二区三区88区| 成人国产视频在线观看| 99久久国产综合精品女不卡| 97aⅴ精品视频一二三区| 欧美日韩中文| 中文亚洲字幕| 久久久久久久高潮| 欧美亚洲一区二区三区四区| 欧美福利一区二区| 精品国产免费人成在线观看| 国产欧美视频在线观看| |精品福利一区二区三区|