Java 反射機制

什么是java反射:

JAVA反射機制是在運行狀態(tài)中狱窘,對于任意一個類,都能夠知道這個類的所有屬性和方法货葬;對于任意一個對象,都能夠調(diào)用它的任意一個方法和屬性劲够;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機制。

注意:反射是指運行時的特性休傍。


java內(nèi)存模型

在運行時征绎,首先你的代碼會先被編譯成一個.class文件,然后被類加載器加載到j(luò)vm內(nèi)存中磨取。

假設(shè)你寫了一段代碼:

Student ?stu = new Student();

你的類Student加載到方法區(qū)人柿,這時會創(chuàng)建一個Student的class對象到堆中,這個只是類的類型對象忙厌,每個類只有一個class對象凫岖,作為方法區(qū)類的數(shù)據(jù)結(jié)構(gòu)的借口。這都是在jvm創(chuàng)建對象之前執(zhí)行逢净,檢查類的加載情況哥放,找到類對應(yīng)的class對象,如果都已經(jīng)加載好爹土,則進行初始化:new Student()甥雕。

上面的代碼,我們自己寫好了需要創(chuàng)建的類胀茵,但是反射卻可以根據(jù)需求社露,動態(tài)的加載需要的類。通過以下代碼可以動態(tài)加載琼娘,例如:

Class stu = Class.forName();

下面使用代碼介紹一下具體的調(diào)用情況:

首先創(chuàng)建Student類峭弟,具體如下:

public class Student {

//---------------構(gòu)造方法-------------------

? ? //(默認的構(gòu)造方法)

? ? Student(String str){

System.out.println("(默認)的構(gòu)造方法 s = " + str);

? ? }

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

? ? public Student(){

System.out.println("調(diào)用了公有、無參構(gòu)造方法執(zhí)行了脱拼。瞒瘸。。");

? ? }

//有一個參數(shù)的構(gòu)造方法

? ? public Student(char name){

System.out.println("姓名:" + name);

? ? }

//有多個參數(shù)的構(gòu)造方法

? ? public Student(String name, int age){

System.out.println("姓名:"+name+"年齡:"+ age);//這的執(zhí)行效率有問題挪拟,以后解決挨务。

? ? }

//受保護的構(gòu)造方法

? ? protected Student(boolean n){

System.out.println("受保護的構(gòu)造方法 n = " + n);

? ? }

//私有構(gòu)造方法

? ? private Student(int age){

System.out.println("私有的構(gòu)造方法? 年齡:"+ age);

? ? }

//**********字段*************//

? ? public Stringname;

? ? protected int age;

? ? char sex;

? ? private StringphoneNum;

? ? @Override

? ? public StringtoString() {

return "Student [name=" +name +", age=" +age +", sex=" +sex

? ? ? ? ? ? ? ? +", phoneNum=" +phoneNum +"]";

? ? }

public void show1(String s){

System.out.println("調(diào)用了:公有的,String參數(shù)的show1(): s = " + s);

? ? }

protected void show2(){

System.out.println("調(diào)用了:受保護的玉组,無參的show2()");

? ? }

void show3(){

System.out.println("調(diào)用了:默認的谎柄,無參的show3()");

? ? }

private Stringshow4(int age){

System.out.println("調(diào)用了,私有的惯雳,并且有返回值的朝巫,int參數(shù)的show4(): age = " + age);

? ? ? ? return "abcd";

? ? }

public static void main(String[] args) {

System.out.println("main方法執(zhí)行了。石景。劈猿。");

? ? }

}

1.獲取Class對象

獲取Class對象有三種方式:

1.1Object.getClass();

1.2獲取數(shù)據(jù)的Class屬性 ?obj.class

1.3通過靜態(tài)方法獲取 Class.forName();

測試類如下:

public?class?Fanshe?{??

public?static?void?main(String[]?args)?{??

//第一種方式獲取Class對象????

Student?stu1?=new?Student();//這一new?產(chǎn)生一個Student對象拙吉,一個Class對象。??

Class?stuClass?=?stu1.getClass();//獲取Class對象??

????????System.out.println(stuClass.getName());??

//第二種方式獲取Class對象 ?

Class?stuClass2?=?Student.class;??

System.out.println(stuClass?==?stuClass2);//判斷第一種方式獲取的Class對象和第二種方式獲取的是否是同一個??

//第三種方式獲取Class對象 ?

try?{??

Class?stuClass3?=?Class.forName("fanshe.Student");//注意此字符串必須是真實路徑揪荣,就是帶包名的類路徑筷黔,包名.類名??

System.out.println(stuClass3?==?stuClass2);//判斷三種方式是否獲取的是同一個Class對象??

}catch?(ClassNotFoundException?e)?{??

????????????e.printStackTrace();??

????????}??

? ? } ?

}

運行main得到的結(jié)果如下:

調(diào)用了公有、無參構(gòu)造方法執(zhí)行了仗颈。佛舱。。

zz.Student

true

true

2.獲取構(gòu)造方法

獲取構(gòu)造方法可以獲取到:

1.所有公有構(gòu)造方法

2.所有構(gòu)造方法

3.獲取某個構(gòu)造方法(公有挨决,私有请祖,默認,受保護)

測試類如下:

public class Constructors {

public static void main(String[] args)throws Exception {

//1.加載Class對象

? ? ? ? Class clazz = Class.forName("zz.Student");

? ? ? ? //2.獲取所有公有構(gòu)造方法

? ? ? ? System.out.println("**********************所有公有構(gòu)造方法*********************************");

? ? ? ? Constructor[] conArray = clazz.getConstructors();

? ? ? ? for(Constructor c : conArray){

System.out.println(c);

? ? ? ? }

System.out.println("************所有的構(gòu)造方法(包括:私有脖祈、受保護肆捕、默認、公有)***************");

? ? ? ? conArray = clazz.getDeclaredConstructors();

? ? ? ? for(Constructor c : conArray){

System.out.println(c);

? ? ? ? }

System.out.println("*****************獲取公有盖高、無參的構(gòu)造方法*******************************");

? ? ? ? Constructor con = clazz.getConstructor(null);

? ? ? ? //1>慎陵、因為是無參的構(gòu)造方法所以類型是一個null,不寫也可以:這里需要的是一個參數(shù)的類型,切記是類型

? ? ? ? //2>或舞、返回的是描述這個無參構(gòu)造函數(shù)的類對象荆姆。

? ? ? ? System.out.println("con = " + con);

? ? ? ? //調(diào)用構(gòu)造方法

? ? ? ? Object obj = con.newInstance();

? ? ? ? //? System.out.println("obj = " + obj);

//? Student stu = (Student)obj;

? ? ? ? System.out.println("******************獲取私有構(gòu)造方法,并調(diào)用*******************************");

? ? ? ? con = clazz.getDeclaredConstructor(char.class);

? ? ? ? System.out.println(con);

? ? ? ? //調(diào)用構(gòu)造方法

? ? ? ? con.setAccessible(true);//暴力訪問(忽略掉訪問修飾符)

? ? ? ? obj = con.newInstance('男');

? ? }

}

輸出結(jié)果如下:

**********************所有公有構(gòu)造方法*********************************

public zz.Student(java.lang.String,int)

public zz.Student()

public zz.Student(char)

************所有的構(gòu)造方法(包括:私有映凳、受保護胆筒、默認、公有)***************

private zz.Student(int)

protected zz.Student(boolean)

public zz.Student(java.lang.String,int)

zz.Student(java.lang.String)

public zz.Student()

public zz.Student(char)

*****************獲取公有诈豌、無參的構(gòu)造方法*******************************

con = public zz.Student()

調(diào)用了公有仆救、無參構(gòu)造方法執(zhí)行了。矫渔。彤蔽。

******************獲取私有構(gòu)造方法,并調(diào)用*******************************

public zz.Student(char)

姓名:男

3.獲取成員變量

測試類如下:

public class Fields {

public static void main(String[] args)throws Exception {

//1.獲取Class對象

? ? ? ? Class stuClass = Class.forName("zz.Student");

? ? ? ? //2.獲取字段

? ? ? ? System.out.println("************獲取所有公有的字段********************");

? ? ? ? Field[] fieldArray = stuClass.getFields();

? ? ? ? for(Field f : fieldArray){

System.out.println(f);

? ? ? ? }

System.out.println("************獲取所有的字段(包括私有庙洼、受保護顿痪、默認的)********************");

? ? ? ? fieldArray = stuClass.getDeclaredFields();

? ? ? ? for(Field f : fieldArray){

System.out.println(f);

? ? ? ? }

System.out.println("*************獲取公有字段**并調(diào)用***********************************");

? ? ? ? Field f = stuClass.getField("name");

? ? ? ? System.out.println(f);

? ? ? ? //獲取一個對象

? ? ? ? Object obj = stuClass.getConstructor().newInstance();//產(chǎn)生Student對象--》Student stu = new Student();

? ? ? ? //為字段設(shè)置值

? ? ? ? f.set(obj, "劉德華");//為Student對象中的name屬性賦值--》stu.name = "劉德華"

? ? ? ? //驗證

? ? ? ? Student stu = (Student)obj;

? ? ? ? System.out.println("驗證姓名:" + stu.name);

? ? ? ? System.out.println("**************獲取私有字段****并調(diào)用********************************");

? ? ? ? f = stuClass.getDeclaredField("phoneNum");

? ? ? ? System.out.println(f);

? ? ? ? f.setAccessible(true);//暴力反射,解除私有限定

? ? ? ? f.set(obj, "18888889999");

? ? ? ? System.out.println("驗證電話:" + stu);

? ? }

}

輸出結(jié)果如下:

************獲取所有公有的字段********************

public java.lang.String zz.Student.name

************獲取所有的字段(包括私有油够、受保護蚁袭、默認的)********************

public java.lang.String zz.Student.name

protected int zz.Student.age

char zz.Student.sex

private java.lang.String zz.Student.phoneNum

*************獲取公有字段**并調(diào)用***********************************

public java.lang.String zz.Student.name

調(diào)用了公有、無參構(gòu)造方法執(zhí)行了石咬。揩悄。。

驗證姓名:劉德華

**************獲取私有字段****并調(diào)用********************************

private java.lang.String zz.Student.phoneNum

驗證電話:Student [name=劉德華, age=0, sex= , phoneNum=18888889999]

4.獲取成員方法

測試類如下:

public class MethodClass {

public static void main(String[] args)throws Exception {

//1.獲取Class對象

? ? ? ? Class stuClass = Class.forName("zz.Student");

? ? ? ? //2.獲取所有公有方法

? ? ? ? System.out.println("***************獲取所有的”公有“方法*******************");

? ? ? ? stuClass.getMethods();

? ? ? ? Method[] methodArray = stuClass.getMethods();

? ? ? ? for(Method m : methodArray){

System.out.println(m);

? ? ? ? }

System.out.println("***************獲取所有的方法鬼悠,包括私有的*******************");

? ? ? ? methodArray = stuClass.getDeclaredMethods();

? ? ? ? for(Method m : methodArray){

System.out.println(m);

? ? ? ? }

System.out.println("***************獲取公有的show1()方法*******************");

? ? ? ? Method m = stuClass.getMethod("show1", String.class);

? ? ? ? System.out.println(m);

? ? ? ? //實例化一個Student對象

? ? ? ? Object obj = stuClass.getConstructor().newInstance();

? ? ? ? m.invoke(obj, "劉德華");

? ? ? ? System.out.println("***************獲取私有的show4()方法******************");

? ? ? ? m = stuClass.getDeclaredMethod("show4", int.class);

? ? ? ? System.out.println(m);

? ? ? ? m.setAccessible(true);//解除私有限定

? ? ? ? Object result = m.invoke(obj, 20);//需要兩個參數(shù)删性,一個是要調(diào)用的對象(獲取有反射)亏娜,一個是實參

? ? ? ? System.out.println("返回值:" + result);

? ? }

}

輸出結(jié)果如下:

***************獲取所有的”公有“方法*******************

public static void zz.Student.main(java.lang.String[])

public java.lang.String zz.Student.toString()

public void zz.Student.show1(java.lang.String)

public final void java.lang.Object.wait() throws java.lang.InterruptedException

public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException

public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException

public boolean java.lang.Object.equals(java.lang.Object)

public native int java.lang.Object.hashCode()

public final native java.lang.Class java.lang.Object.getClass()

public final native void java.lang.Object.notify()

public final native void java.lang.Object.notifyAll()

***************獲取所有的方法,包括私有的*******************

public static void zz.Student.main(java.lang.String[])

public java.lang.String zz.Student.toString()

public void zz.Student.show1(java.lang.String)

private java.lang.String zz.Student.show4(int)

protected void zz.Student.show2()

void zz.Student.show3()

***************獲取公有的show1()方法*******************

public void zz.Student.show1(java.lang.String)

調(diào)用了公有蹬挺、無參構(gòu)造方法執(zhí)行了维贺。。汗侵。

調(diào)用了:公有的幸缕,String參數(shù)的show1(): s = 劉德華

***************獲取私有的show4()方法******************

private java.lang.String zz.Student.show4(int)

調(diào)用了,私有的晰韵,并且有返回值的,int參數(shù)的show4(): age = 20

返回值:abcd

5.反射main方法

測試類如下:

public class Main {

public static void main(String[] args) {

try {

//1熟妓、獲取Student對象的字節(jié)碼

? ? ? ? ? ? Class clazz = Class.forName("zz.Student");

? ? ? ? ? ? //2雪猪、獲取main方法

? ? ? ? ? ? Method methodMain = clazz.getMethod("main", String[].class);//第一個參數(shù):方法名稱,第二個參數(shù):方法形參的類型起愈,

? ? ? ? ? ? //3只恨、調(diào)用main方法

? ? ? ? ? ? // methodMain.invoke(null, new String[]{"a","b","c"});

? ? ? ? ? ? //第一個參數(shù),對象類型抬虽,因為方法是static靜態(tài)的官觅,所以為null可以,第二個參數(shù)是String數(shù)組阐污,這里要注意在jdk1.4時是數(shù)組休涤,jdk1.5之后是可變參數(shù)

? ? ? ? ? ? //這里拆的時候?qū)? new String[]{"a","b","c"} 拆成3個對象。笛辟。功氨。所以需要將它強轉(zhuǎn)。

? ? ? ? ? ? methodMain.invoke(null, (Object)new String[]{"a","b","c"});//方式一

? ? ? ? ? ? // methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二

? ? ? ? }catch (Exception e) {

e.printStackTrace();

? ? ? ? }

}

}

輸出結(jié)果如下:

main方法執(zhí)行了手幢。捷凄。。

6.通過配置文件反射

測試類如下:

public class Demo {

public static void main(String[] args)throws Exception {

//通過反射獲取Class對象

? ? ? ? Class stuClass = Class.forName(getValue("className"));//"zz.Student"

? ? ? ? //2獲取show()方法

? ? ? ? Method m = stuClass.getMethod(getValue("methodName"));//show

? ? ? ? //3.調(diào)用show()方法

? ? ? ? m.invoke(stuClass.getConstructor().newInstance());

? ? }

//此方法接收一個key围来,在配置文件中獲取相應(yīng)的value

? ? public static StringgetValue(String key)throws IOException{

Properties pro =new Properties();//獲取配置文件的對象

? ? ? ? FileReader in =new FileReader("demo.txt");//獲取輸入流

? ? ? ? pro.load(in);//將流加載到配置文件對象中

? ? ? ? in.close();

? ? ? ? return pro.getProperty(key);//返回根據(jù)key獲取的value值

? ? }

}

配置文件如下:

className = zz.Student

methodName = show1

輸出結(jié)果如下:

調(diào)用了:公有的跺涤,String參數(shù)的show1(): s =

由此可見,調(diào)用其他方法只需要改寫配置文件即可监透,或者引入新的類也可以直接改寫配置文件桶错。

7.java泛型檢查

測試類如下:

public class Demo2 {

public static void main(String[] args)throws Exception{

ArrayList strList =new ArrayList<>();

? ? ? ? strList.add("aaa");

? ? ? ? strList.add("bbb");

? ? ? ? //? strList.add(100);

? ? ? ? //獲取ArrayList的Class對象,反向的調(diào)用add()方法才漆,添加數(shù)據(jù)

? ? ? ? Class listClass = strList.getClass(); //得到 strList 對象的字節(jié)碼 對象

? ? ? ? //獲取add()方法

? ? ? ? Method m = listClass.getMethod("add", Object.class);

? ? ? ? //調(diào)用add()方法

? ? ? ? m.invoke(strList, 100);

? ? ? ? //遍歷集合

? ? ? ? for(Object obj : strList){

System.out.println(obj);

? ? ? ? }

}

}

輸出結(jié)果如下:

aaa

bbb

100



個人公號:【排骨肉段】牛曹,可以關(guān)注一下。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末醇滥,一起剝皮案震驚了整個濱河市黎比,隨后出現(xiàn)的幾起案子超营,更是在濱河造成了極大的恐慌,老刑警劉巖阅虫,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件演闭,死亡現(xiàn)場離奇詭異,居然都是意外死亡颓帝,警方通過查閱死者的電腦和手機米碰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來购城,“玉大人吕座,你說我怎么就攤上這事”癜澹” “怎么了吴趴?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長侮攀。 經(jīng)常有香客問我锣枝,道長,這世上最難降的妖魔是什么兰英? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任撇叁,我火速辦了婚禮,結(jié)果婚禮上畦贸,老公的妹妹穿的比我還像新娘陨闹。我一直安慰自己,他們只是感情好家制,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布正林。 她就那樣靜靜地躺著,像睡著了一般颤殴。 火紅的嫁衣襯著肌膚如雪觅廓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天涵但,我揣著相機與錄音杈绸,去河邊找鬼。 笑死矮瘟,一個胖子當(dāng)著我的面吹牛瞳脓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播澈侠,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼劫侧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起烧栋,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤写妥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后审姓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體珍特,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年魔吐,在試婚紗的時候發(fā)現(xiàn)自己被綠了扎筒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡酬姆,死狀恐怖嗜桌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辞色,我是刑警寧澤症脂,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站淫僻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏壶唤。R本人自食惡果不足惜雳灵,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闸盔。 院中可真熱鬧悯辙,春花似錦、人聲如沸迎吵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽击费。三九已至拢蛋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蔫巩,已是汗流浹背谆棱。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留圆仔,地道東北人垃瞧。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像坪郭,于是被迫代替她去往敵國和親个从。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法嗦锐,內(nèi)部類的語法嫌松,繼承相關(guān)的語法,異常的語法意推,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • 一豆瘫、概述 Java反射機制定義 Java反射機制是在運行狀態(tài)中,對于任意一個類菊值,都能夠知道這個類中的所有屬性和方法...
    CoderZS閱讀 1,639評論 0 26
  • 1.反射機制是什么: 反射機制是在運行狀態(tài)中外驱,對于任意一個類,都能夠知道這個類的所有屬性和方法腻窒;對于任意一個對象昵宇,...
    蠻大人我們走閱讀 347評論 0 0
  • 基本概念 java的反射機制是動態(tài)獲取類的信息以及動態(tài)調(diào)用對象的方法。這種機制允許程序在運行時通過reflecti...
    YONGSSU的技術(shù)站點閱讀 778評論 0 10
  • 喜歡就勇敢地去做 有夢就堅持地去追 不要問別人信不信 要問問自己做不做
    一棵樹閱讀 134評論 0 0