java反射

什么是java反射機(jī)制

動(dòng)態(tài)語言

當(dāng)程序運(yùn)行時(shí)碌更,允許改變程序結(jié)構(gòu)或變量類型涯竟,這種語言稱為動(dòng)態(tài)語言。

靜態(tài)語言

靜態(tài)語言是在編譯時(shí)變量的數(shù)據(jù)類型即可確定的語言袖订。

反射機(jī)制

JAVA反射機(jī)制是在運(yùn)行狀態(tài)中慰毅,對(duì)于任意一個(gè)類隘截,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象汹胃,都能夠調(diào)用它的任意一個(gè)方法和屬性婶芭;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語言的反射機(jī)制。

IT行業(yè)里這么說着饥,沒有反射也就沒有框架犀农,現(xiàn)有的框架都是以反射為基礎(chǔ)。在實(shí)際項(xiàng)目開發(fā)中宰掉,用的最多的是框架呵哨,填的最多的是類,反射這一概念就是將框架和類揉在一起的調(diào)和劑轨奄。所以孟害,反射才是接觸項(xiàng)目開發(fā)的敲門磚!

java反射機(jī)制常用的類

Class

在面向?qū)ο蟮氖澜缋锱材猓f事萬物皆是對(duì)象挨务。而在java語言中,static修飾的東西不是對(duì)象玉组,但是它屬于類谎柄。普通的數(shù)據(jù)類型不是對(duì)象,例如:int a = 5;它不是面向?qū)ο蠊喏ǎ撬衅浒b類 Integer 或者分裝類來彌補(bǔ)了它谷誓。

實(shí)例化對(duì)象有三種表示方法:

public class Demo(){
F f=new F();
//第一種表達(dá)方式
Class c1=F.class;//這種表達(dá)方式同時(shí)也告訴了我們?nèi)魏我粋€(gè)類都有一個(gè)隱含的靜態(tài)成員變量class
//第二種表達(dá)方式
Class c2=f.getClass();//這種表達(dá)方式在已知了該類的對(duì)象的情況下通過getClass方法獲取
//第三種表達(dá)方式
Class c3 = null;
try {
c3 = Class.forName("com.text.F");//類的全稱
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
class F{}

其次他們都是同一個(gè)Class嗎

System.out.println(c1 == c2)?  or  System.out.println(c1 == c3)?

答案肯定是ture。這表明不論c1,orc2,orc3都代表了F類的類類型反粥,也就是說一個(gè)類只可能是Class類的一個(gè)實(shí)例對(duì)象。

理解了Class的概念糙臼,我們也可以通過類的類類型創(chuàng)建該類的對(duì)象實(shí)例,用c1 or c2 or c3的newInstance()方法:

Public class Demo1{
try {
Foo foo = (Foo)c1.newInstance();//foo就表示F類的實(shí)例化對(duì)象
foo.print();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}}
class F{
void print(){
}
}

方法的反射

public class ClassUtil {
public static void printClassMethodMessage(Object obj){
//要獲取類的信息》》首先我們要獲取類的類類型
Class c = obj.getClass();
//我們知道Object類是一切類的父類恩商,所以我們傳遞的是哪個(gè)子類的對(duì)象变逃,c就是該子類的類類型。
//接下來我們要獲取類的名稱
System.out.println("類的名稱是:"+c.getName());
/*
*我們知道怠堪,萬事萬物都是對(duì)象揽乱,方法也是對(duì)象,是誰的對(duì)象呢粟矿?
* 在java里面凰棉,方法是Method類的對(duì)象
*一個(gè)成員方法就是一個(gè)Method的對(duì)象,那么Method就封裝了對(duì)這個(gè)成員
*方法的操作
*/
//如果我們要獲得所有的方法陌粹,可以用getMethods()方法撒犀,這個(gè)方法獲取的是所有的Public的函數(shù),包括父類繼承而來的掏秩。如果我們要獲取所有該類自己聲明的方法或舞,就可以用getDeclaredMethods()方法,這個(gè)方法是不問訪問權(quán)限的蒙幻。
Method[] ms = c.getMethods();//c.getDeclaredMethods()
//接下來我們拿到這些方法之后干什么映凳?我們就可以獲取這些方法的信息,比如方法的名字邮破。
//首先我們要循環(huán)遍歷這些方法
for(int i = 0; i < ms.length;i++){
//然后可以得到方法的返回值類型的類類型
Class returnType = ms[i].getReturnType();
//得到方法的返回值類型的名字
System.out.print(returnType.getName()+" ");
//得到方法的名稱
System.out.print(ms[i].getName()+"(");
//獲取參數(shù)類型--->得到的是參數(shù)列表的類型的類類型
Class[] paramTypes = ms[i].getParameterTypes();
for (Class class1 : paramTypes) {
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}
}

總結(jié)思路:

通過方法的反射得到該類的名稱步驟:

  1. 獲取該類的類類型
  2. 通過類類型獲取類的方法(getMethods())
  3. 循環(huán)遍歷所獲取到的方法
  4. 通過這些方法的getReturnType()得到返回值類型的類類型诈豌,又通過該類類型得到返回值類型的名字
  5. getName()得到方法的名稱,getParameterTypes()獲取這個(gè)方法里面的參數(shù)類型的類類型决乎。

成員變量的反射

首先我們需要認(rèn)識(shí)到成員變量也是對(duì)象队询,是java.lang.reflect.Field類的對(duì)象,那么也就是說Field類封裝了關(guān)于成員變量的操作构诚。既然它封裝了成員變量蚌斩,我們又該如何獲取這些成員變量呢?它有這么一個(gè)方法:

public class ClassUtil {
public static void printFieldMessage(Object obj){
Class c = obj.getClass();
//Field[] fs = c.getFields();
}

這里的getFields()方法獲取的所有的public的成員變量的信息范嘱。和方法的反射那里public的成員變量送膳,也有一個(gè)獲取所有自己聲明的成員變量的信息:

Field[] fs = c.getDeclaredFields();

我們得到它之后,可以進(jìn)行遍歷(既然封裝了Field的信息丑蛤,那么我們就可以得到Field類型)

for (Field field : fs) {
//得到成員變量的類型的類類型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成員變量的名稱
String fieldName = field.getName();
System.out.println(typeName+" "+fieldName);
}

構(gòu)造函數(shù)的反射

不論是方法的反射叠聋、成員變量的反射、構(gòu)造函數(shù)的反射受裹,我們只需要知道:要想獲取類的信息碌补,首先得獲取類的類類型虏束。

public static void printConMessage(Object obj){
Class c = obj.getClass();
/*
* 首先構(gòu)造函數(shù)也是對(duì)象,是java.lang.Constructor類的對(duì)象
* 也就是java.lang. Constructor中封裝了構(gòu)造函數(shù)的信息
* 和前面說到的一樣厦章,它也有兩個(gè)方法:
* getConstructors()方法獲取所有的public的構(gòu)造函數(shù)
* getDeclaredConstructors()方法得到所有的自己聲明的構(gòu)造函數(shù)
*/
//Constructor[] cs = c.getConstructors();
Constructor[] cs = c.getDeclaredConstructors();
for (Constructor constructor : cs) {
//我們知道構(gòu)造方法是沒有返回值類型的镇匀,但是我們可以:
System.out.print(constructor.getName()+"(");
//獲取構(gòu)造函數(shù)的參數(shù)列表》》得到的是參數(shù)列表的類類型
Class[] paramTypes = constructor.getParameterTypes();
for (Class class1 : paramTypes) {
System.out.print(class1.getName()+",");
}
System.out.println(")");
}
}

Class類的動(dòng)態(tài)加載類

靜態(tài)加載類

一般就是指new ClassName(),這個(gè)在編譯時(shí)就會(huì)檢查。無論你這個(gè)類用不用袜啃,代碼邏輯能不能執(zhí)行到汗侵,編譯期都會(huì)對(duì)其編譯。不存在這個(gè)類無法通過編譯群发。

動(dòng)態(tài)加載類

我們想要的就是我用那個(gè)類就加載那個(gè)類晰韵,也就是常說的運(yùn)行時(shí)刻加載,動(dòng)態(tài)加載類熟妓。Class.forName("ClassName")雪猪,就是所謂的動(dòng)態(tài)加載,動(dòng)態(tài)加載的類在源程序編譯時(shí)可以缺席滑蚯。

我們可以建這么一個(gè)類:

Class All{
Public static void start(){
try{
Class cl= Class.forName(args[0]);
//通過類類型浪蹂,創(chuàng)建該類的對(duì)象
cl.newInstance();
}catch(Exception e){
e.printStackTrace();
}
}
}

前面我們?cè)诜治鯟lass實(shí)例化對(duì)象的方式的時(shí)候,Class.forName(“類的全稱”)告材,它不僅僅表示了類的類類型坤次,還表示了動(dòng)態(tài)加載類。當(dāng)我們javac All.java的時(shí)候斥赋,它不會(huì)報(bào)任何錯(cuò)誤缰猴,也就是說在編譯的時(shí)候是沒有錯(cuò)誤的。只有當(dāng)我們具體用某個(gè)類的時(shí)候疤剑,那個(gè)類不存在滑绒,它才會(huì)報(bào)錯(cuò)。
如果加載的類是B類隘膘,就需要:

B bt = (B) cl.newInstance();

萬一加載的是C類呢疑故,可以改成

C ct = (C) cl.newInstance();

但是如果我想用很多的類或者加載很多的類,該怎么辦弯菊?我們可以統(tǒng)一一個(gè)標(biāo)準(zhǔn)纵势,不論C類還是B類或者其他的類,比如定義一個(gè)標(biāo)準(zhǔn)

Stand s = (Stand) cl.newInstance();

只要B類和C類都是這個(gè)標(biāo)準(zhǔn)的就行了管钳。

Class All{
Public static void start(){
try{
Class cl= Class.forName(args[0]);
//通過類類型钦铁,創(chuàng)建該類的對(duì)象
Stand s = (Stand) cl.newInstance();
s.start();
}catch(Exception e){
e.printStackTrace();
}
}
}
interface Stand {
Public void start();
}

現(xiàn)在如果我想要用B類,我們只需要:

Class B implements Stand{
Public void start(){
System.out.print("B...satrt");
}
}

結(jié)果

B...satrt
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末才漆,一起剝皮案震驚了整個(gè)濱河市牛曹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌醇滥,老刑警劉巖黎比,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件超营,死亡現(xiàn)場離奇詭異,居然都是意外死亡阅虫,警方通過查閱死者的電腦和手機(jī)糟描,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來书妻,“玉大人,你說我怎么就攤上這事躬拢《懵模” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵聊闯,是天一觀的道長工猜。 經(jīng)常有香客問我,道長菱蔬,這世上最難降的妖魔是什么篷帅? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮拴泌,結(jié)果婚禮上魏身,老公的妹妹穿的比我還像新娘。我一直安慰自己蚪腐,他們只是感情好箭昵,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著回季,像睡著了一般家制。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泡一,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天颤殴,我揣著相機(jī)與錄音,去河邊找鬼鼻忠。 笑死涵但,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粥烁。 我是一名探鬼主播贤笆,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼讨阻!你這毒婦竟也來了芥永?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤钝吮,失蹤者是張志新(化名)和其女友劉穎埋涧,沒想到半個(gè)月后板辽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棘催,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年劲弦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片醇坝。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡邑跪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呼猪,到底是詐尸還是另有隱情画畅,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布宋距,位于F島的核電站轴踱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谚赎。R本人自食惡果不足惜淫僻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望壶唤。 院中可真熱鬧雳灵,春花似錦、人聲如沸视粮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蕾殴。三九已至笑撞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钓觉,已是汗流浹背茴肥。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留荡灾,地道東北人瓤狐。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像批幌,于是被迫代替她去往敵國和親础锐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一荧缘、概述 Java反射機(jī)制定義 Java反射機(jī)制是在運(yùn)行狀態(tài)中皆警,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類中的所有屬性和方法...
    CoderZS閱讀 1,631評(píng)論 0 26
  • 一截粗、概述 1信姓、Java反射機(jī)制(Java-Reflect): 在運(yùn)行狀態(tài)中鸵隧,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類中的所...
    年少懵懂丶流年夢(mèng)閱讀 4,379評(píng)論 0 5
  • java通常是先有類再有對(duì)象意推,有對(duì)象我就可以調(diào)用方法或者屬性豆瘫。反射其實(shí)是通過Class對(duì)象來調(diào)用類里面的方法。通過...
    yzw12138閱讀 303評(píng)論 0 0
  • 前言 現(xiàn)在在我們構(gòu)建自己或公司的項(xiàng)目中菊值,或多或少都會(huì)依賴幾個(gè)流行比較屌的第三方庫外驱,比如:Butter Knife、...
    戴定康閱讀 3,929評(píng)論 0 17
  • 寫在前面:什么是java反射機(jī)制腻窒?我們又為什么要學(xué)它略步?當(dāng)程序運(yùn)行時(shí),允許改變程序結(jié)構(gòu)或變量類型定页,這種語言稱為動(dòng)態(tài)語...
    wxyjj閱讀 17,156評(píng)論 29 156