前言
反射是被視為動態語言的關鍵,反射機制允許程序在執行期間借助于Reflection API取得任何類得內部信息,并能夠直接操作任意對象得內部屬性和方法(包括私有)。
加載完類之后,在方法區中就會產生一個Class類型對象,這個對象就包含了完整得類得結構信息。我們可以通過這個對象看到類得結構。這個對象就像就像一面鏡子,透過這個鏡子可以看到類得結構,所以,我們形象得稱之為:反射。
所以我們首先簡單的講一下類加載,然后在講反射機制。
類加載
類加載步驟
分為三步:加載、鏈接、初始化
加載Loading
作用:在內存中生成一個代表這個類的Class對象,作為方法區中這和類的各種數據的訪問入口。
什么時候加載?
- new
- Class.forName(“包名。類名”)
怎么加載?
Bootstrap(根加載器,加載$JAVA_HOME/jre/lib/rt.jar包內的class文件,包含java運行環境所需的基礎類)
ExtClass(加載$JAVA_HOME/jre/lib/ext/.jar目錄下的class文件)
AppClass(用于——加載當前應用的classpath的所有類)
鏈接 Linking
該過程分三個階段:驗證、準備、解析
驗證:驗證階段用于確保加載的Class文件的字節流包含的信息是否符合虛擬機要求,保證其合法性。
準備階段: 為類變量(靜態變量)分配內存并跟根據對象類型賦對應的默認值。
解析階段:用于將符號引用轉換為直接引用。
初始化 initialization
執行類的構造方法的過程
反射技術
運行時動態訪問對象的屬性和方法。
Class對象
上面我們簡單的了解了以下類加載機制。
那我們如何得到Class對象呢?
通常我們又三種方法:
第一種,使用 Class.forName 靜態方法。 前提:已明確類的全路徑名。
第二種,使用 .class 方法。 說明:僅適合在編譯前就已經明確要操作的 Class
第三種,使用類對象的 getClass() 方法。 適合有對象示例的情況下
代碼:
package com.dyit.clazz;
public class GetClass {
//定義一個內部類
static class A {
public A() {
}
public void print() {
System.out.println("內部類");
}
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//得到class對象
System.out.println(A.class);
A b = new A();
System.out.println(b.getClass());
System.out.println(Class.forName("com.dyit.clazz.GetClass$A"));
}
}
結果截圖:
那我們拿到Class對象可以干什么呢?
之前我們類的實例化有三種方式:
new 關鍵字
克隆
反序列化
現在我們可以通過類的Class對象創建類的實例
通過Class.newInstance()可以得到類的實例;
可以通過Class.getSimpleName()得到類的名稱
代碼如下:
package com.dyit.clazz;
public class ClassDemo {
//定義一個內部類
static class A {
public A() {
}
public void print() {
System.out.println("內部類");
}
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
//得到Class對象
Class<A> a = A.class;
//得到類的名稱
System.out.println(a.getName());
System.out.println(a.getSimpleName());
//創建實例
A b = a.newInstance();
//調用方法
b.print();
}
}
結果:
Field類
描述類中的屬性,(數值)域
首先通過Class對象得到所有的屬性
Class.getDeclaredFields()
通過設置field.setAccessible(true)可以訪問私有屬性。
field.get(c) 得到c關于這和屬性的值
field.getName()得到屬性的名稱
field.getType()得到屬性的類型
field.getType()。getSimpleName()得到屬性的簡單名稱
可以通過set方法設置對象屬性的值:field.set(c, 999.99)
如需轉載,請注明文章出處和來源網址:http://www.rs2pl.com/html/h65268.shtml