1. 程式人生 > >Java反射機制能夠獲取的信息,與應用

Java反射機制能夠獲取的信息,與應用

rri 代理 pan [] reflect 語言 子類 list tro

一、什麽是Java反射機制?

【1】反射機制是在運行狀態中,對於任何一個類,都能夠知道這個類的所有屬性和方法;

【2】對於任意一個對象,都能夠調用它的任意一個屬性和方法;

像這種動態獲取類的信息以及動態調用對象的方法的騷操作稱為java語言的反射機制。


二、Java反射機制能夠獲取及操作哪些信息?

【1】獲取類的包名 + 類名

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 public class TestReflect {
 4 
 5     public static void main(String[] args) throws ClassNotFoundException {
 6         Class<?> class1 = TestReflect.class;
 7         Class<?> class2 = new TestReflect().getClass();
 8         Class<?> class3 = Class.forName("com.zyy.test.reflect.TestReflect");
 9         
10         System.out.println("包名+類名:" + class1.getName());
11         System.out.println("類名" + class1.getSimpleName());
12         System.out.println("包名+類名:" + class2.getName());
13         System.out.println("類名" + class2.getSimpleName());
14         System.out.println("包名+類名:" + class3.getName());
15         System.out.println("類名" + class3.getSimpleName());
16         
17         /*
18          打印結果如下:
19             包名+類名:com.zyy.test.reflect.TestReflect
20             類名TestReflect
21             包名+類名:com.zyy.test.reflect.TestReflect
22             類名TestReflect
23             包名+類名:com.zyy.test.reflect.TestReflect
24             類名TestReflect
25         */
26     }
27 
28 }
技術分享

【2】獲取某個類的父類與實現的接口信息

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 import java.io.Serializable;
 4 
 5 public class TestReflect implements Serializable{
 6 
 7     private static final long serialVersionUID = -8047590384784013451L;
 8 
 9     public static void main(String[] args) throws ClassNotFoundException {
10         Class<?> clazz = Class.forName("com.zyy.test.reflect.TestReflect");
11         //獲取父類信息
12         System.out.println("父類:" + clazz.getSuperclass().getName());
13         //獲取實現的所有接口信息
14         Class<?>[] interfaces = clazz.getInterfaces();
15         for (int i = 0; i < interfaces.length; i++) {
16             System.out.println("接口:" + interfaces[i].getName());
17         }
18         
19         /*打印結果如下:
20             父類:java.lang.Object
21             接口:java.io.Serializable
22          */
23     }
24 
25 }
技術分享

【3】獲取某個類的構造信息以及使用構造進行賦值

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.InvocationTargetException;
 5 import java.math.BigDecimal;
 7 
 8 public class TestReflect {
 9     
10     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, 
11         IllegalArgumentException, InvocationTargetException {
12         
13         Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");
14         Constructor<?>[] constructors = clazz.getConstructors();
15         
16         for (int i = 0; i < constructors.length; i++) {
17             System.out.println("構造" + i + constructors[i].getName() + "的參數為:");
18             //獲取構造的參數信息
19             Class<?>[] types = constructors[i].getParameterTypes();
20             for (int j = 0; j < types.length; j++) {
21                 System.out.println(types[j].getName() + " ");
22             }
23         }
24         
25         /*打印結果:
26              構造0com.zyy.test.reflect.BookFacaed的參數為:
27             java.lang.String 
28             java.math.BigDecimal 
29             構造1com.zyy.test.reflect.BookFacaed的參數為:
30             java.lang.String 
31             構造2com.zyy.test.reflect.BookFacaed的參數為:
32          */
33         
34         //實例化擁有2個參數的構造方法
35         BookFacaed bookFacaed = (BookFacaed)constructors[0].newInstance("《數據結構》", new BigDecimal(100));
36         System.out.println(bookFacaed);    //調用實體的toString方法打印
37         
38         //通過反射機制直接實例化對象
39         BookFacaed bookFacaed2 = (BookFacaed)clazz.newInstance();
40         bookFacaed2.setName("《數據結構》");
41         bookFacaed2.setPrice(new BigDecimal(100));
42         System.out.println(bookFacaed2);
43     }
44     
45 }
46 
47 class BookFacaed {
48     private String name;
49     
50     private BigDecimal price;
51     
52     public BookFacaed () {}
53     
54     public BookFacaed (String name) {
55         this.name = name;
56     }
57 
58     public BookFacaed (String name, BigDecimal price) {
59         this.name = name;
60         this.price = price;
61     }
62     
63     public String getName() {
64         return name;
65     }
66 
67     public void setName(String name) {
68         this.name = name;
69     }
70 
71     public BigDecimal getPrice() {
72         return price;
73     }
74 
75     public void setPrice(BigDecimal price) {
76         this.price = price;
77     }
78     
79     @Override
80     public String toString() {
81         return name + "的價格為:" + price;
82     }
83 }
技術分享

【4】獲取某個類的所有屬性信息

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 import java.lang.reflect.Field;
 4 import java.lang.reflect.Modifier;public class TestReflect {
 5     
 6     public static void main(String[] args) throws ClassNotFoundException {
 7         Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");
 8         Field[] fields = clazz.getDeclaredFields();
 9         for (int i = 0; i < fields.length; i++) {
10             //獲得類屬性的修飾符
11             String pri = Modifier.toString(fields[i].getModifiers());
12             //獲得類屬性的類型
13             Class<?> type = fields[i].getType();
14             
15             System.out.println(pri + " " + type.getSimpleName() + " " + fields[i].getName());
16             /*打印結果:
17                 private String name
18                 private BigDecimal price
19              */
20         }
21         
22         /*如果要獲取類的接口或者父類的屬性使用下面的方法獲取*/
23         Field[] fields2 = clazz.getFields();
24     }
25     
26 }
技術分享

【5】獲取某個類的所有方法及其屬性信息

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 import java.lang.reflect.Method;
 4 import java.lang.reflect.Modifier;
 5 import java.math.BigDecimal;
 6 
 7 
 8 public class TestReflect {
 9     
10     public static void main(String[] args) throws ClassNotFoundException {
11         Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");
12         
13         Method[] methods = clazz.getMethods();
14         for (int i = 0; i < methods.length; i++) {
15             System.out.println("方法" + (i + 1));
16             //獲取方法的修飾符
17             String pri = Modifier.toString(methods[i].getModifiers());
18             //獲取方法的返回類型
19             Class<?> type = methods[i].getReturnType();
20             //獲取方法的持有參數
21             Class<?>[] params = methods[i].getParameterTypes();
22             for (int j = 0; j < params.length; j++) {
23                 System.out.println(params[j].getName());
24             }
25             //獲取方法的拋出異常
26             Class<?>[] excTypes = methods[i].getExceptionTypes();
27             for (int j = 0; j < excTypes.length; j++) {
28                 System.out.println(excTypes[j].getName());
29             }
30         }
31     }
32     
33 }
技術分享

【6】反射機制調用某個類的某個方法

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 import java.lang.reflect.InvocationTargetException;
 4 import java.lang.reflect.Method;
 5 import java.math.BigDecimal;
 6 
 7 public class TestReflect {
 8     
 9     public static void main(String[] args) throws NoSuchMethodException, SecurityException, ClassNotFoundException, 
10         IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
11         
12         Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");
13         //調用BookFacaed的addBook()方法
14         Method method = clazz.getMethod("addBook", String.class);
15         method.invoke(clazz.newInstance(), "《數據結構》");
16     }
17     
18 }
19 
20 class BookFacaed {
21     private String name;
22     
23     private BigDecimal price;
24     
25     public BookFacaed () {}
26     
27     public BookFacaed (String name) {
28         this.name = name;
29     }
30 
31     public BookFacaed (String name, BigDecimal price) {
32         this.name = name;
33         this.price = price;
34     }
35     
36     public void addBook(String name) {
37         System.out.println("添加書:" + name);
38     }
39     
40     public String getName() {
41         return name;
42     }
43 
44     public void setName(String name) {
45         this.name = name;
46     }
47 
48     public BigDecimal getPrice() {
49         return price;
50     }
51 
52     public void setPrice(BigDecimal price) {
53         this.price = price;
54     }
55     
56     @Override
57     public String toString() {
58         return name + "的價格為:" + price;
59     }
60 }
技術分享

【7】通過反射機制操作某個類的屬性

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 import java.lang.reflect.Field;
 4 import java.math.BigDecimal;
 5 
 6 public class TestReflect {
 7     
 8     public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, 
 9         SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException {
10         
11         Class<?> clazz = Class.forName("com.zyy.test.reflect.BookFacaed");
12         Object obj = clazz.newInstance();
13         //調用BookFacaed的name屬性,並賦值
14         Field field = clazz.getDeclaredField("name");
15         field.setAccessible(true); //操作屬性修飾符為private則必須用此申明
16         field.set(obj, "《數據結構》");
17         
18         System.out.println(field.get(obj));
19     }
20     
21 }
技術分享

三、Java反射機制能夠幫助我們做什麽?

【1】打破泛型的約束

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 import java.lang.reflect.InvocationTargetException;
 4 import java.lang.reflect.Method;
 5 import java.math.BigDecimal;
 6 import java.util.ArrayList;
 7 import java.util.List;
 8 
 9 public class TestReflect {
10     
11     public static void main(String[] args) throws NoSuchMethodException, SecurityException, 
12         IllegalAccessException, IllegalArgumentException, InvocationTargetException {
13         
14         List<Integer> list = new ArrayList<Integer>();
15         //設定了以上泛型之後,list集合中是無法插入String或者其他類型的數據的
16         //通過泛型我們便可打破這個約束,代碼如下
17         Method method = list.getClass().getMethod("add", Object.class);
18         method.invoke(list, "看插入了一個String數據");
19         
20         System.out.println(list.get(0));
21     }
22     
23 }
技術分享

【2】反射機制實現動態代理

  Spring的一個核心設計思想便是AOP(面向切面編程),那麽AOP是通過動態代理實現的,而動態代理則用到了反射機制;

  用了反射機制的好處在於,一個代理就能處理所有的委托,而不用一個委托類就創建一個代理;

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 
 7 
 8 public class TestReflect {
 9     
10     public static void main(String[] args) {
11         //創建代理類並綁定委托類
12         FruitProxy proxy = new FruitProxy();
13         Fruit fruit = (Fruit) proxy.bind(new Apple());
14         fruit.eatFruit();
15     }
16     
17 }
18 
19 interface Fruit {
20     public void eatFruit();
21 }
22 
23 //委托類
24 class Apple implements Fruit {
25     public void eatFruit() {
26         System.out.println("eat Apple");
27     }
28 }
29 
30 //代理類
31 class FruitProxy implements InvocationHandler{
32     private Object obj;
33     
34     //綁定對象
35     public Object bind(Object obj) {
36         this.obj = obj;
37         return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
38     }
39     
40     @Override
41     public Object invoke(Object proxy, Method method, Object[] args)
42             throws Throwable {
43         System.out.println("這裏添加執行內容,<aop:before/>標簽熟悉吧,作用一樣");
44         Method result = (Method) method.invoke(obj, args);
45         System.out.println("這裏添加執行內容,<aop:after/>標簽熟悉吧,作用一樣");
46         
47         return result;
48     }
49     
50 }
技術分享

【3】反射機制應用於工廠模式

對於普通的工廠,新增一個子類的時候,工廠就需要進行調整,而加入反射機制後,工廠則不需要關心你有多少個子類;

技術分享
 1 package com.zyy.test.reflect;
 2 
 3 public class TestReflect {
 4     
 5     public static void main(String[] args) throws InstantiationException, 
 6         IllegalAccessException, ClassNotFoundException {
 7         
 8         Fruit fruit = (Fruit) Factory.getInstance("com.zyy.test.reflect.Orange");
 9         fruit.eatFruit();
10     }
11     
12 }
13 
14 interface Fruit {
15     public void eatFruit();
16 }
17 
18 class Apple implements Fruit {
19     public void eatFruit() {
20         System.out.println("eat Apple");
21     }
22 }
23 
24 class Orange implements Fruit {
25     public void eatFruit() {
26         System.out.println("eat Orange");
27     }
28 }
29 
30 class Factory {
31     public static Object getInstance (String className) throws InstantiationException, 
32         IllegalAccessException, ClassNotFoundException {
33         
34         Object obj = Class.forName(className).newInstance();
35         return obj;
36     }
37     
38 }

Java反射機制能夠獲取的信息,與應用