本篇文章依舊采用小例子來(lái)說(shuō)明,因?yàn)槲沂冀K覺(jué)的,案例驅(qū)動(dòng)是最好的,要不然只看理論的話,看了也不懂,不過(guò)建議大家在看完文章之后,在回過(guò)頭去看看理論,會(huì)有更好的理解。
下面開(kāi)始正文。
【案例1】通過(guò)一個(gè)對(duì)象獲得完整的包名和類名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package Reflect; /** * 通過(guò)一個(gè)對(duì)象獲得完整的包名和類名 * */ class Demo{ //other codes... } class hello{ public static void main(String[] args) { Demo demo= new Demo(); System.out.println(demo.getClass().getName()); } } |
【運(yùn)行結(jié)果】:Reflect.Demo
添加一句:所有類的對(duì)象其實(shí)都是Class的實(shí)例。
【案例2】實(shí)例化Class類對(duì)象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package Reflect; class Demo{ //other codes... } class hello{ public static void main(String[] args) { Class<?> demo1= null ; Class<?> demo2= null ; Class<?> demo3= null ; try { //一般盡量采用這種形式 demo1=Class.forName( "Reflect.Demo" ); } catch (Exception e){ e.printStackTrace(); } demo2= new Demo().getClass(); demo3=Demo. class ; System.out.println( "類名稱 " +demo1.getName()); System.out.println( "類名稱 " +demo2.getName()); System.out.println( "類名稱 " +demo3.getName()); } } |
【運(yùn)行結(jié)果】:
類名稱 Reflect.Demo
類名稱 Reflect.Demo
類名稱 Reflect.Demo
【案例3】通過(guò)Class實(shí)例化其他類的對(duì)象
通過(guò)無(wú)參構(gòu)造實(shí)例化對(duì)象
1
2
3
4
|
public Person(String name, int age) { this .age=age; this .name=name; } |
然后繼續(xù)運(yùn)行上面的程序,會(huì)出現(xiàn):
所以大家以后再編寫(xiě)使用Class實(shí)例化其他類的對(duì)象的時(shí)候,一定要自己定義無(wú)參的構(gòu)造函數(shù)
【案例】通過(guò)Class調(diào)用其他類中的構(gòu)造函數(shù) (也可以通過(guò)這種方式通過(guò)Class創(chuàng)建其他類的對(duì)象)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
package Reflect; import java.lang.reflect.Constructor; class Person{ public Person() { } public Person(String name){ this .name=name; } public Person( int age){ this .age=age; } public Person(String name, int age) { this .age=age; this .name=name; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString(){ return "[" + this .name+ " " + this .age+ "]" ; } private String name; private int age; } class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } Person per1= null ; Person per2= null ; Person per3= null ; Person per4= null ; //取得全部的構(gòu)造函數(shù) Constructor<?> cons[]=demo.getConstructors(); try { per1=(Person)cons[ 0 ].newInstance(); per2=(Person)cons[ 1 ].newInstance( "Rollen" ); per3=(Person)cons[ 2 ].newInstance( 20 ); per4=(Person)cons[ 3 ].newInstance( "Rollen" , 20 ); } catch (Exception e){ e.printStackTrace(); } System.out.println(per1); System.out.println(per2); System.out.println(per3); System.out.println(per4); } } |
【運(yùn)行結(jié)果】:
[null 0]
[Rollen 0]
[null 20]
[Rollen 20]
【案例】
返回一個(gè)類實(shí)現(xiàn)的接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package Reflect; interface China{ public static final String name= "Rollen" ; public static int age= 20 ; public void sayChina(); public void sayHello(String name, int age); } class Person implements China{ public Person() { } public Person(String sex){ this .sex=sex; } public String getSex() { return sex; } public void setSex(String sex) { this .sex = sex; } @Override public void sayChina(){ System.out.println( "hello ,china" ); } @Override public void sayHello(String name, int age){ System.out.println(name+ " " +age); } private String sex; } class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } //保存所有的接口 Class<?> intes[]=demo.getInterfaces(); for ( int i = 0 ; i < intes.length; i++) { System.out.println( "實(shí)現(xiàn)的接口 " +intes[i].getName()); } } } |
【運(yùn)行結(jié)果】:
實(shí)現(xiàn)的接口 Reflect.China
(注意,以下幾個(gè)例子,都會(huì)用到這個(gè)例子的Person類,所以為節(jié)省篇幅,此處不再粘貼Person的代碼部分,只粘貼主類hello的代碼)
【案例】:取得其他類中的父類
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } //取得父類 Class<?> temp=demo.getSuperclass(); System.out.println( "繼承的父類為: " +temp.getName()); } } |
【運(yùn)行結(jié)果】
繼承的父類為: java.lang.Object
【案例】:獲得其他類中的全部構(gòu)造函數(shù)
這個(gè)例子需要在程序開(kāi)頭添加import java.lang.reflect.*;
然后將主類編寫(xiě)為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } Constructor<?>cons[]=demo.getConstructors(); for ( int i = 0 ; i < cons.length; i++) { System.out.println( "構(gòu)造方法: " +cons[i]); } } } |
【運(yùn)行結(jié)果】:
構(gòu)造方法: public Reflect.Person()
構(gòu)造方法: public Reflect.Person(java.lang.String)
但是細(xì)心的讀者會(huì)發(fā)現(xiàn),上面的構(gòu)造函數(shù)沒(méi)有public 或者private這一類的修飾符
下面這個(gè)例子我們就來(lái)獲取修飾符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } Constructor<?>cons[]=demo.getConstructors(); for ( int i = 0 ; i < cons.length; i++) { Class<?> p[]=cons[i].getParameterTypes(); System.out.print( "構(gòu)造方法: " ); int mo=cons[i].getModifiers(); System.out.print(Modifier.toString(mo)+ " " ); System.out.print(cons[i].getName()); System.out.print( "(" ); for ( int j= 0 ;j<p.length;++j){ System.out.print(p[j].getName()+ " arg" +i); if (j<p.length- 1 ){ System.out.print( "," ); } } System.out.println( "){}" ); } } } |
【運(yùn)行結(jié)果】:
構(gòu)造方法: public Reflect.Person(){}
構(gòu)造方法: public Reflect.Person(java.lang.String arg1){}
有時(shí)候一個(gè)方法可能還有異常,呵呵。下面看看:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } Method method[]=demo.getMethods(); for ( int i= 0 ;i<method.length;++i){ Class<?> returnType=method[i].getReturnType(); Class<?> para[]=method[i].getParameterTypes(); int temp=method[i].getModifiers(); System.out.print(Modifier.toString(temp)+ " " ); System.out.print(returnType.getName()+ " " ); System.out.print(method[i].getName()+ " " ); System.out.print( "(" ); for ( int j= 0 ;j<para.length;++j){ System.out.print(para[j].getName()+ " " + "arg" +j); if (j<para.length- 1 ){ System.out.print( "," ); } } Class<?> exce[]=method[i].getExceptionTypes(); if (exce.length> 0 ){ System.out.print( ") throws " ); for ( int k= 0 ;k<exce.length;++k){ System.out.print(exce[k].getName()+ " " ); if (k<exce.length- 1 ){ System.out.print( "," ); } } } else { System.out.print( ")" ); } System.out.println(); } } } |
【案例】接下來(lái)讓我們?nèi)〉闷渌惖娜繉傩园桑詈笪抑v這些整理在一起,也就是通過(guò)class取得一個(gè)類的全部框架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
class hello { public static void main(String[] args) { Class<?> demo = null ; try { demo = Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } System.out.println( "===============本類屬性========================" ); // 取得本類的全部屬性 Field[] field = demo.getDeclaredFields(); for ( int i = 0 ; i < field.length; i++) { // 權(quán)限修飾符 int mo = field[i].getModifiers(); String priv = Modifier.toString(mo); // 屬性類型 Class<?> type = field[i].getType(); System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";" ); } System.out.println( "===============實(shí)現(xiàn)的接口或者父類的屬性========================" ); // 取得實(shí)現(xiàn)的接口或者父類的屬性 Field[] filed1 = demo.getFields(); for ( int j = 0 ; j < filed1.length; j++) { // 權(quán)限修飾符 int mo = filed1[j].getModifiers(); String priv = Modifier.toString(mo); // 屬性類型 Class<?> type = filed1[j].getType(); System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";" ); } } } |
【運(yùn)行結(jié)果】:
===============本類屬性========================
private java.lang.String sex;
===============實(shí)現(xiàn)的接口或者父類的屬性========================
public static final java.lang.String name;
public static final int age;
【案例】其實(shí)還可以通過(guò)反射調(diào)用其他類中的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class hello { public static void main(String[] args) { Class<?> demo = null ; try { demo = Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } try { //調(diào)用Person類中的sayChina方法 Method method=demo.getMethod( "sayChina" ); method.invoke(demo.newInstance()); //調(diào)用Person的sayHello方法 method=demo.getMethod( "sayHello" , String. class , int . class ); method.invoke(demo.newInstance(), "Rollen" , 20 ); } catch (Exception e) { e.printStackTrace(); } } } |
【運(yùn)行結(jié)果】:
hello ,china
Rollen 20
【案例】調(diào)用其他類的set和get方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
class hello { public static void main(String[] args) { Class<?> demo = null ; Object obj= null ; try { demo = Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } try { obj=demo.newInstance(); } catch (Exception e) { e.printStackTrace(); } setter(obj, "Sex" , "男" ,String. class ); getter(obj, "Sex" ); } /** * @param obj * 操作的對(duì)象 * @param att * 操作的屬性 * */ public static void getter(Object obj, String att) { try { Method method = obj.getClass().getMethod( "get" + att); System.out.println(method.invoke(obj)); } catch (Exception e) { e.printStackTrace(); } } /** * @param obj * 操作的對(duì)象 * @param att * 操作的屬性 * @param value * 設(shè)置的值 * @param type * 參數(shù)的屬性 * */ public static void setter(Object obj, String att, Object value, Class<?> type) { try { Method method = obj.getClass().getMethod( "set" + att, type); method.invoke(obj, value); } catch (Exception e) { e.printStackTrace(); } } } // end class |
【運(yùn)行結(jié)果】:
男
【案例】通過(guò)反射操作屬性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class hello { public static void main(String[] args) throws Exception { Class<?> demo = null ; Object obj = null ; demo = Class.forName( "Reflect.Person" ); obj = demo.newInstance(); Field field = demo.getDeclaredField( "sex" ); field.setAccessible( true ); field.set(obj, "男" ); System.out.println(field.get(obj)); } } // end class |
【案例】通過(guò)反射取得并修改數(shù)組的信息:
1
2
3
4
5
6
7
8
9
10
11
12
|
import java.lang.reflect.*; class hello{ public static void main(String[] args) { int [] temp={ 1 , 2 , 3 , 4 , 5 }; Class<?>demo=temp.getClass().getComponentType(); System.out.println( "數(shù)組類型: " +demo.getName()); System.out.println( "數(shù)組長(zhǎng)度 " +Array.getLength(temp)); System.out.println( "數(shù)組的第一個(gè)元素: " +Array.get(temp, 0 )); Array.set(temp, 0 , 100 ); System.out.println( "修改之后數(shù)組第一個(gè)元素為: " +Array.get(temp, 0 )); } } |
【運(yùn)行結(jié)果】:
數(shù)組類型: int
數(shù)組長(zhǎng)度 5
數(shù)組的第一個(gè)元素: 1
修改之后數(shù)組第一個(gè)元素為: 100
【案例】通過(guò)反射修改數(shù)組大小
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
class hello{ public static void main(String[] args) { int [] temp={ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; int [] newTemp=( int [])arrayInc(temp, 15 ); print(newTemp); System.out.println( "=====================" ); String[] atr={ "a" , "b" , "c" }; String[] str1=(String[])arrayInc(atr, 8 ); print(str1); } /** * 修改數(shù)組大小 * */ public static Object arrayInc(Object obj, int len){ Class<?>arr=obj.getClass().getComponentType(); Object newArr=Array.newInstance(arr, len); int co=Array.getLength(obj); System.arraycopy(obj, 0 , newArr, 0 , co); return newArr; } /** * 打印 * */ public static void print(Object obj){ Class<?>c=obj.getClass(); if (!c.isArray()){ return ; } System.out.println( "數(shù)組長(zhǎng)度為: " +Array.getLength(obj)); for ( int i = 0 ; i < Array.getLength(obj); i++) { System.out.print(Array.get(obj, i)+ " " ); } } } |
【運(yùn)行結(jié)果】:
數(shù)組長(zhǎng)度為: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================
數(shù)組長(zhǎng)度為: 8
a b c null null null null null
動(dòng)態(tài)代理
【案例】首先來(lái)看看如何獲得類加載器:
1
2
3
4
5
6
7
8
9
|
class test{ } class hello{ public static void main(String[] args) { test t= new test(); System.out.println( "類加載器 " +t.getClass().getClassLoader().getClass().getName()); } } |
【程序輸出】:
類加載器 sun.misc.Launcher$AppClassLoader
其實(shí)在java中有三種類類加載器。
1)Bootstrap ClassLoader 此加載器采用c++編寫(xiě),一般開(kāi)發(fā)中很少見(jiàn)。
2)Extension ClassLoader 用來(lái)進(jìn)行擴(kuò)展類的加載,一般對(duì)應(yīng)的是jre\lib\ext目錄中的類
3)AppClassLoader 加載classpath指定的類,是最常用的加載器。同時(shí)也是java中默認(rèn)的加載器。
如果想要完成動(dòng)態(tài)代理,首先需要定義一個(gè)InvocationHandler接口的子類,已完成代理的具體操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package Reflect; import java.lang.reflect.*; //定義項(xiàng)目接口 interface Subject { public String say(String name, int age); } // 定義真實(shí)項(xiàng)目 class RealSubject implements Subject { @Override public String say(String name, int age) { return name + " " + age; } } class MyInvocationHandler implements InvocationHandler { private Object obj = null ; public Object bind(Object obj) { this .obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), this ); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object temp = method.invoke( this .obj, args); return temp; } } class hello { public static void main(String[] args) { MyInvocationHandler demo = new MyInvocationHandler(); Subject sub = (Subject) demo.bind( new RealSubject()); String info = sub.say( "Rollen" , 20 ); System.out.println(info); } } |
【運(yùn)行結(jié)果】:
Rollen 20
類的生命周期
在一個(gè)類編譯完成之后,下一步就需要開(kāi)始使用類,如果要使用一個(gè)類,肯定離不開(kāi)JVM。在程序執(zhí)行中JVM通過(guò)裝載,鏈接,初始化這3個(gè)步驟完成。
類的裝載是通過(guò)類加載器完成的,加載器將.class文件的二進(jìn)制文件裝入JVM的方法區(qū),并且在堆區(qū)創(chuàng)建描述這個(gè)類的java.lang.Class對(duì)象。用來(lái)封裝數(shù)據(jù)。 但是同一個(gè)類只會(huì)被類裝載器裝載以前
鏈接就是把二進(jìn)制數(shù)據(jù)組裝為可以運(yùn)行的狀態(tài)。
鏈接分為校驗(yàn),準(zhǔn)備,解析這3個(gè)階段
校驗(yàn)一般用來(lái)確認(rèn)此二進(jìn)制文件是否適合當(dāng)前的JVM(版本),
準(zhǔn)備就是為靜態(tài)成員分配內(nèi)存空間,。并設(shè)置默認(rèn)值
解析指的是轉(zhuǎn)換常量池中的代碼作為直接引用的過(guò)程,直到所有的符號(hào)引用都可以被運(yùn)行程序使用(建立完整的對(duì)應(yīng)關(guān)系)
完成之后,類型也就完成了初始化,初始化之后類的對(duì)象就可以正常使用了,直到一個(gè)對(duì)象不再使用之后,將被垃圾回收。釋放空間。
當(dāng)沒(méi)有任何引用指向Class對(duì)象時(shí)就會(huì)被卸載,結(jié)束類的生命周期
將反射用于工廠模式
先來(lái)看看,如果不用反射的時(shí)候,的工廠模式吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/** * @author Rollen-Holt 設(shè)計(jì)模式之 工廠模式 */ interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println( "Apple" ); } } class Orange implements fruit{ public void eat(){ System.out.println( "Orange" ); } } // 構(gòu)造工廠類 // 也就是說(shuō)以后如果我們?cè)谔砑悠渌膶?shí)例的時(shí)候只需要修改工廠類就行了 class Factory{ public static fruit getInstance(String fruitName){ fruit f= null ; if ( "Apple" .equals(fruitName)){ f= new Apple(); } if ( "Orange" .equals(fruitName)){ f= new Orange(); } return f; } } class hello{ public static void main(String[] a){ fruit f=Factory.getInstance( "Orange" ); f.eat(); } } |
這樣,當(dāng)我們?cè)谔砑右粋€(gè)子類的時(shí)候,就需要修改工廠類了。如果我們添加太多的子類的時(shí)候,改的就會(huì)很多。
現(xiàn)在我們看看利用反射機(jī)制:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
package Reflect; interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println( "Apple" ); } } class Orange implements fruit{ public void eat(){ System.out.println( "Orange" ); } } class Factory{ public static fruit getInstance(String ClassName){ fruit f= null ; try { f=(fruit)Class.forName(ClassName).newInstance(); } catch (Exception e) { e.printStackTrace(); } return f; } } class hello{ public static void main(String[] a){ fruit f=Factory.getInstance( "Reflect.Apple" ); if (f!= null ){ f.eat(); } } } |
現(xiàn)在就算我們添加任意多個(gè)子類的時(shí)候,工廠類就不需要修改。
上面的愛(ài)嗎雖然可以通過(guò)反射取得接口的實(shí)例,但是需要傳入完整的包和類名。而且用戶也無(wú)法知道一個(gè)接口有多少個(gè)可以使用的子類,所以我們通過(guò)屬性文件的形式配置所需要的子類。
下面我們來(lái)看看: 結(jié)合屬性文件的工廠模式
首先創(chuàng)建一個(gè)fruit.properties的資源文件,
內(nèi)容為:
1
2
|
apple=Reflect.Apple orange=Reflect.Orange |
然后編寫(xiě)主類代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
package Reflect; import java.io.*; import java.util.*; interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println( "Apple" ); } } class Orange implements fruit{ public void eat(){ System.out.println( "Orange" ); } } //操作屬性文件類 class init{ public static Properties getPro() throws FileNotFoundException, IOException{ Properties pro= new Properties(); File f= new File( "fruit.properties" ); if (f.exists()){ pro.load( new FileInputStream(f)); } else { pro.setProperty( "apple" , "Reflect.Apple" ); pro.setProperty( "orange" , "Reflect.Orange" ); pro.store( new FileOutputStream(f), "FRUIT CLASS" ); } return pro; } } class Factory{ public static fruit getInstance(String ClassName){ fruit f= null ; try { f=(fruit)Class.forName(ClassName).newInstance(); } catch (Exception e) { e.printStackTrace(); } return f; } } class hello{ public static void main(String[] a) throws FileNotFoundException, IOException{ Properties pro=init.getPro(); fruit f=Factory.getInstance(pro.getProperty( "apple" )); if (f!= null ){ f.eat(); } } } |
以上這篇java反射深入剖析(推薦)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。