【類反射】類反射原理和獲取Class對象的三種方式


什么是類反射—原理?

☆什么是反射

(1)Java反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為Java語言的反射機制。

(2)反射(Reflection)是Java程序開發語言的特征之一,它允許運行中的Java程序對自身進行檢查, 也稱自審,並能直接操作程序的內部屬性。例如,使用它能獲得Java類中各成員的名稱並顯示出來。

(3)Java的這一能力在實際應用中應用得很多,在其它的程序語言中根本就不存在這一特性。例如,Pascal、C或者C++中就沒有辦法在程序中獲得函數定義相關的信息。

(4)JavaBean是類反射的實際應用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過類反射動態的載入並取得Java組件(類)的屬性。后面學習的各種框架,基本上都會有反射的使用。

這里寫圖片描述

☆反射引例(HelloWorld、USB)

反射最大的好處就是解耦

  1. 最簡單的類反射:(相當於HelloWorld)

    一個ReflectionHelloWorld類演示:

 1 import java.lang.reflect.Constructor;
 2 import java.lang.reflect.Field;
 3 import java.lang.reflect.Method;
 4 
 5 /**
 6  * 1、類反射使用的步驟:<br>
 7  *      (1)Class c=Class.forName("類全名:包名[.子包名].類名");<br>
 8  *      (2)調用c對象中的成員方法:Field(字段)、Method(方法)、Constructor(構造方法)、Modifier(靜態方法和常量)<br>
 9  *      (3)遍歷出所有信息<br>
10  */
11 public class ReflectionHelloWorld {
12     public static void main(String[] args) {
13         try {
14             Class c=Class.forName("cn.yu.reflect.test.UserModel");
15             /*
16              * 提供有關類或接口的單個字段信息,以及對他的動態訪問權限
17              */
18             Field[] flds=c.getDeclaredFields();
19             for(Field fild:flds){
20                 System.out.println(fild);
21             }
22             System.out.println("------------------------");
23             /*
24              *  提供關於類的單個構造方法的信息以及對它的訪問權限。得到的構造方法只能是public類型的。
25              */
26             Constructor[] cons=c.getConstructors();
27             for(Constructor con:cons){
28                 System.out.println(con);
29             }
30             System.out.println("------------------------");
31             /*
32              * 返回 Method 對象的一個數組,這些對象反映此 Class 對象表示的類或接口聲明的所有方法,
33              * 包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法。
34              */
35             Method[] ms=c.getDeclaredMethods();
36             for(Method m:ms){
37                 System.out.println(m);
38             }
39             System.out.println("------------------------");
40         } catch (ClassNotFoundException e) {
41             e.printStackTrace();
42         }
43     }
44 }

UserModel類:

 1 import java.io.Serializable;
 2 
 3 /**
 4  * 用戶uuid,name
 5  */
 6 interface Intera{
 7     public void aa();
 8 }
 9 public class UserModel implements Serializable{
10     private static final long serialVersionUID = 1L;
11     private String uuid;
12     private String name;
13     private int type;
14     private String pwd;
15 
16     public UserModel(String uuid, String name, int type, String pwd) {
17         super();
18         this.uuid = uuid;
19         this.name = name;
20         this.type = type;
21         this.pwd = pwd;
22     }
23 
24     public UserModel(String uuid, String name, int type) {
25         super();
26         this.uuid = uuid;
27         this.name = name;
28         this.type = type;
29     }
30 
31     public UserModel(){
32 
33     }
34     public void a(){
35         System.out.println("我是接口的抽象方法");
36     }
37     public String getUuid() {
38         return uuid;
39     }
40     public void setUuid(String uuid) {
41         this.uuid = uuid;
42     }
43     public String getName() {
44         return name;
45     }
46     public void setName(String name) {
47         this.name = name;
48     }
49     public int getType() {
50         return type;
51     }
52     public void setType(int type) {
53         this.type = type;
54     }
55     public String getPwd() {
56         return pwd;
57     }
58     public void setPwd(String pwd) {
59         this.pwd = pwd;
60     }
61     public static long getSerialversionuid() {
62         return serialVersionUID;
63     }
64     @Override
65     public int hashCode() {
66         final int prime = 31;
67         int result = 1;
68         result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
69         return result;
70     }
71     @Override
72     public boolean equals(Object obj) {
73         if (this == obj)
74             return true;
75         if (obj == null)
76             return false;
77         if (getClass() != obj.getClass())
78             return false;
79         UserModel other = (UserModel) obj;
80         if (uuid == null) {
81             if (other.uuid != null)
82                 return false;
83         } else if (!uuid.equals(other.uuid))
84             return false;
85         return true;
86     }
87     @Override
88     public String toString() {
89         return "ID:\t" + uuid + "  , \t" + name + "\t , " + (type);
90     }
91 }

運行結果:

private static final long cn.yu.reflect.test.UserModel.serialVersionUID
private java.lang.String cn.yu.reflect.test.UserModel.uuid
private java.lang.String cn.yu.reflect.test.UserModel.name
private int cn.yu.reflect.test.UserModel.type
private java.lang.String cn.yu.reflect.test.UserModel.pwd
------------------------
public cn.yu.reflect.test.UserModel()
public cn.yu.reflect.test.UserModel(java.lang.String,java.lang.String,int)
public cn.yu.reflect.test.UserModel(java.lang.String,java.lang.String,int,java.lang.String)
------------------------
public java.lang.String cn.yu.reflect.test.UserModel.toString()
public int cn.yu.reflect.test.UserModel.hashCode()
public boolean cn.yu.reflect.test.UserModel.equals(java.lang.Object)
public java.lang.String cn.yu.reflect.test.UserModel.getName()
public int cn.yu.reflect.test.UserModel.getType()
public void cn.yu.reflect.test.UserModel.setName(java.lang.String)
public static long cn.yu.reflect.test.UserModel.getSerialversionuid()
public java.lang.String cn.yu.reflect.test.UserModel.getUuid()
public void cn.yu.reflect.test.UserModel.setType(int)
public void cn.yu.reflect.test.UserModel.setPwd(java.lang.String)
public void cn.yu.reflect.test.UserModel.a()
public java.lang.String cn.yu.reflect.test.UserModel.getPwd()
public void cn.yu.reflect.test.UserModel.setUuid(java.lang.String)
------------------------

反射使用的三個步驟

用於反射的類,如Method,可以在java.lang.reflect包中找到。使用這些類的時候必須要遵循三個步驟:

  1. 第一步:獲得你想操作的類的java.lang.Class對象。在運行中的Java程序中,用java.lang.Class類來描述類和接口等。
  2. 第二步:調用諸如getDeclaredMethods的方法,取得該類中定義的所有方法的列表。
  3. 第三步:使用反射的API來操作這些信息。

如下面這段代碼:

1 Class c = Class.forName("java.lang.String");
2 Method ms[] = c.getDeclaredMethods();
3 System.out.println(ms[0].toString());

它將以文本方式打印出String中定義的第一個方法的原型。

獲取Class對象的三種方式:

★ 方式一

通過對象的getClass方法進行獲取。這種方式需要具體的類和該類的對象,以及調用getClass方法。

★ 方式二

任何數據類型(包括基本數據類型)都具備着一個靜態的屬性class,通過它可直接獲取到該類型對應的Class對象。這種方式要使用具體的類,然后調用類中的靜態屬性class完成,無需調用方法,性能更好。

★ 方式三

通過Class.forName()方法獲取。這種方式僅需使用類名,就可以獲取該類的Class對象,更有利於擴展。

代碼演示:

 1 import org.junit.Test;
 2 /**
 3  * 1、演示獲取Class c對象的三種方法
 4  */
 5 public class ReflectGetClass {
 6 
 7     /**
 8      * 法1:通過對象---對象.getClass()來獲取c(一個Class對象)
 9      */
10     @Test
11     public void get1(){
12         Person p=new Person("Jack", 23);
13         Class c=p.getClass();//來自Object方法
14     }
15 
16     /**
17      * 法2:通過類(類型)---任何數據類型包括(基本數據類型)都有一個靜態的屬性class ,他就是c 一個Class對象
18      */
19     @Test
20     public void get2(){
21         Class c=Person.class;
22         Class c2=int.class;
23     }
24 
25     /**
26      * 法3:通過字符串(類全名 )---能夠實現解耦:Class.forName(str)
27      */
28     @Test
29     public void get3(){
30         try {
31             Class c=Class.forName("cn.hncu.reflect.test.Person");
32         } catch (ClassNotFoundException e) {
33             e.printStackTrace();
34         }
35     }
36 
37 }

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM