基礎知識:Java反射機制

來源:互聯網
上載者:User

標籤:

反射機制的原理

??

一般來說,如果想產生一個類的對象,那麼運行這個程式的JVM會去確認這個類的class對象是否已經載入。如果尚未載入,那麼JVM會根據類名尋找.class檔案,並將其載入,一旦這個類的class對象被載入記憶體,它就可以被用來建立這個類的的所有對象

??

另外如果遇到一個未知類型的引用,(JVM?)通常會採用強制類型轉換的形式來得到開發人員想要的類型引用,如果執行了錯誤的類型轉換,則會報一個ClassCastException異常

??

在以上兩個過程中,Class類一直都在起作用,因為Class類執行個體包含的是一個類的全部資訊,包括方法、屬性、構造器等

??

如果不是在啟動時去建立這個Class執行個體,而是在運行時獲得這個Class類執行個體,那麼我們就可以動態去載入一個類,動態調用類的方法,已經動態去訪問一個類的屬性,反射機制就是為這種情境而產生的,反射機制的出發點就在於JVM會為每個類建立一個java.lang.Class類的執行個體,通過該對象可以擷取該類的全部資訊,然後通過java.lang.reflect包下的API以達到以上所述的動態需求

??

三種情況會導致一個Java類被載入到JVM中

??

Student stu=new Student();

使用該類建立對象

??

System.out.println(student.count)

訪問該類的靜態成員

??

Class.forName("com.Student");

使用Class類的靜態方法forName方法,動態載入一個指定類名的類

ps…JDBC匯入驅動類就是一個很常用的例子

??

三種得到一個類Class對象的方法

??

Class類forName方法返回的就是一個類的對象的引用

??

通過類的Class屬性

Class<Student> clazz=Student.class;

??

通過getClass方法,這個方法是從Object類繼承下來的

Student stu=new Student();

Class<Student> clazz=stu.getClass();

??

ps…獲得類的Class對象後,就可以用這個對象建立和調用和訪問這個類中的各種東西了

ps…Class類對象的方法getName、getConstructor、getMethod、newInstance

??

Field的用法:操作類的成員變數

??

通過Class類的getDeclaredField方法可以獲得一個Field類對象的引用,有了這個對象的引用之後,就可以調用該對象的getXXX方法,其中XXX包括int,double,byte等獲得某個成員變數

??

通過Field對象的使用來按照某一規則比較兩個對象的大小

??

private static FieldReflect compareReflect(FieldReflect obj1,FieldReflect obj2)

??

三種獲得的方式,本質上是三種獲得Class對象的方式

??

//1

Field field=obj1.getClass().getDeclaredField("age");

//2

Field field=FieldReflect.class.getDeclaredField("age");

//3

Class clazz = Class.forName("com.FieldReflect.FieldReflect");

??

得到Class對象之後,就可以調用getDeclaredField方法得到Field對象的引用了

??

Field field = clazz.getDeclaredField("age");

??

得到Field對象的引用之後,就可以調用getXXX方法獲得某一成員變數了

??

Field的用法:操作類的私人成員

??

首先我們寫一個類,類的成員變數為私人

??

class PrivateFieldReflectClass {

private String name;

private int age;

public PrivateFieldReflectClass(String name, int age) {

super();

this.name = name;

this.age = age;

}

}

然後我們在主類中去通過反射機製得到類的Field類

??

public class PrivateFieldReflectTest {

public static void main(String[] args) {

PrivateFieldReflectClass fieldReflect1 = new PrivateFieldReflectClass(

"Tong", 23);

// 訪問私人變數

Class<PrivateFieldReflectClass> clazz = PrivateFieldReflectClass.class;

Field field = clazz.getDeclaredField("age");

// field.setAccessible(true);

System.out.println(field.getInt(fieldReflect1));

}

}

??

當我們試圖去訪問私人變數時,會發生錯誤java.lang.IllegalAccessException

如果我們想去訪問私人變數,需要把Field的執行個體對象設定Accessible屬性為true即可

??

Field的用法:覆蓋toString方法,使其能夠動態更改類對象的toString展示

??

需要覆蓋類中的toString方法,主要思想就是用類對象的getDeclaredFields方法得到Field數組,迴圈遍曆,得到相應的Name和Value

??

class DataObject{

private String name;

private int age;

private String description;

private String other;

public DataObject(String name, int age, String description, String other) {

super();

this.name = name;

this.age = age;

this.description = description;

this.other = other;

}

@Override

public String toString() {

StringBuffer sb=new StringBuffer();

Field[] fields=DataObject.class.getDeclaredFields();

for (Field field : fields) {

sb.append(field.getName());

sb.append("=");

sb.append(field.get(this));

sb.append("\n");

}

return sb.toString();

}

}

??

Method的用法:操作類的方法

??

Method類,代表的是類的方法,包括靜態和非靜態,與Field類似,通過反射機制,具體來說就是通過Class類對象的getMethod方法可以獲得Method類的對象,然後通過該對象額invoke方法,將類名作為參數傳入該方法,即可完成方法的調用

??

首先類中定義兩個方法

??

public class MethodReflect {

public void m1() {

System.out.println("method 1");

}

public void m2() {

System.out.println("method 2");

}

}

??

然後在main函數就可以利用反射機制擷取並調用想要的方法了

反射機制的過程仍舊是先得到類的對象的引用,然後通過類對象的getDeclaredMethod方法得到方法類對象的引用,然後建立一個類的對象,然後利用方法對象的invoke方法將剛建立的類對象作為參數傳入,注意,這裡如果方法有參數,需要將參數列表也作為參數傳入invoke中

??

Class clazz=MethodReflect.class;

Method method=clazz.getDeclaredMethod("m1");

MethodReflect methodReflect=new MethodReflect();

method.invoke(methodReflect);

??

Constructor類的用法:利用反射機制執行個體化一個類

??

一般來說,我們可以通過new關鍵字執行個體化一個類,也就是建立一個類的對象,而如何通過反射機制執行個體話一個類呢,其實不管是通過new關鍵字還是通過反射,都是去調用類的建構函式,如果是去調用無參的建構函式,我們可以使用Class的newInstance方法。如果是要用到有參的建構函式的話,我們就需要用到反射包下的Constructor類

??

首先也是要得到類的對象的引用

??

Class<Student> clazz1=Student.class;

//無參:通過newInstance

Student student1=clazz1.newInstance();

//有參:通過構造器

Constructor<Student> constructor=clazz1.getConstructor(String.class,int.class);

student1=constructor.newInstance("Tong",23);

??

基礎知識:Java反射機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.