說明
對于JDK源碼分析的文章,僅僅記錄我認為重要的地方。源碼的細節實在太多,不可能面面俱到地寫清每個邏輯。所以我的JDK源碼分析
,著重在JDK的體系架構層面,具體源碼可以參考:http://www.cnblogs.com/skywang12345/category/455711.html。
反射簡介
在運行狀態中,我們可以根據“類的部分已知的信息
”來還原“類的全部的信息
”。
類的部分已知的信息:
- 類名
- 類的對象
類的全部信息
- 屬性
- 方法
- 繼承關系
- Annotation注解
根據類名構造類
代碼示例
User類
public class User implements Serializable{
private static final long serialVersionUID = 1510634274152200118L;
private int id;
private String passWord;
public User() {
System.out.println("Create user... ");
}
public User(int id, String passWord) {
this.id = id;
this.passWord = passWord;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
@Override
public String toString() {
return "User [id=" + id + ", passWord=" + passWord + "]";
}
}
根據類名,構造類的代碼:
@Test
public void testReflection() throws Exception {
Class<?> clazz = Class.forName("test.User");
User user = (User) clazz.newInstance();
System.out.println("user = " + user);
}
輸出:
Create user...
user = User [id=0, passWord=null]
獲取 class 對象
@Test
public void testClazz() throws Exception {
Class<?> clazz1 = Class.forName("test.User");
Class clazz2 = User.class;
Class clazz3 = new User().getClass();
System.out.println("clazz1: " + clazz1);
System.out.println("clazz2: " + clazz2);
System.out.println("clazz3: " + clazz3);
}
輸出:
Create user...
clazz1: class test.User
clazz2: class test.User
clazz3: class test.User
class 的 API
- 構造函數
- 成員方法
- 成員變量
- 類的其它信息(如注解、包名、類名、繼承關系等等)
構造函數
// 獲取“參數是parameterTypes”的public的構造函數
public Constructor getConstructor(Class[] parameterTypes)
// 獲取全部的public的構造函數
public Constructor[] getConstructors()
// 獲取“參數是parameterTypes”的,并且是類自身聲明的構造函數,包含public、protected和private方法。
public Constructor getDeclaredConstructor(Class[] parameterTypes)
// 獲取類自身聲明的全部的構造函數,包含public、protected和private方法。
public Constructor[] getDeclaredConstructors()
// 如果這個類是“其它類的構造函數中的內部類”,調用getEnclosingConstructor()就是這個類所在的構造函數;若不存在,返回null。
public Constructor getEnclosingConstructor()
測試:
@Test
public void testConstructor() throws Exception {
Class<?> clazz = Class.forName("test.User");
Constructor<?> constructor = clazz.getDeclaredConstructor(null);
Object object1 = constructor.newInstance();
System.out.println(object1);
Constructor<?> constructor2 = clazz.getDeclaredConstructor(new Class[] {int.class, String.class});
Object object2 = constructor2.newInstance(1, "123456");
System.out.println(object2);
}
輸出:
Create user...
User [id=0, passWord=null]
User [id=1, passWord=123456]
可以調用默認的構造函數,也可以通過
clazz.getDeclaredConstructor(new Class[] {int.class, String.class})
來調用User的含參構造函數
public User(int id, String passWord) {
this.id = id;
this.passWord = passWord;
}
成員方法
// 獲取“名稱是name,參數是parameterTypes”的public的函數(包括從基類繼承的、從接口實現的所有public函數)
public Method getMethod(String name, Class[] parameterTypes)
// 獲取全部的public的函數(包括從基類繼承的、從接口實現的所有public函數)
public Method[] getMethods()
// 獲取“名稱是name,參數是parameterTypes”,并且是類自身聲明的函數,包含public、protected和private方法。
public Method getDeclaredMethod(String name, Class[] parameterTypes)
// 獲取全部的類自身聲明的函數,包含public、protected和private方法。
public Method[] getDeclaredMethods()
// 如果這個類是“其它類中某個方法的內部類”,調用getEnclosingMethod()就是這個類所在的方法;若不存在,返回null。
public Method getEnclosingMethod()
可以判斷類中是否含有某個方法,也可以調用類中的任何一個方法(包括私有方法)。
@Test
public void testMethod() throws Exception {
Class<?> clazz = Class.forName("test.User");
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println();
Method printInfo = clazz.getDeclaredMethod("printInfo", new Class[]{});
User user = (User) clazz.newInstance();
printInfo.invoke(user, null);
}
輸出:
Create user...
public java.lang.String test.User.toString()
public int test.User.getId()
public void test.User.printInfo()
public void test.User.setId(int)
public void test.User.setPassWord(java.lang.String)
public java.lang.String test.User.getPassWord()
User [id=0, passWord=null]
成員變量
// 獲取“名稱是name”的public的成員變量(包括從基類繼承的、從接口實現的所有public成員變量)
public Field getField(String name)
// 獲取全部的public成員變量(包括從基類繼承的、從接口實現的所有public成員變量)
public Field[] getFields()
// 獲取“名稱是name”,并且是類自身聲明的成員變量,包含public、protected和private成員變量。
public Field getDeclaredField(String name)
// 獲取全部的類自身聲明的成員變量,包含public、protected和private成員變量。
public Field[] getDeclaredFields()
@Test
public void testField() throws Exception {
Class<?> clazz = Class.forName("test.User");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
// 創建并通過反射,修改一個 private 變量 id
User user = (User) clazz.newInstance();
Field field = clazz.getDeclaredField("id");
field.setAccessible(true);
field.set(user, 123);
user.printInfo();
}
輸出:
private static final long test.User.serialVersionUID
private int test.User.id
private java.lang.String test.User.passWord
Create user...
User [id=123, passWord=null]
我們可以看到,User中對于id的定義:
private int id;
而在測試用例中,可以獲取對象中私有的id變量,并直接修改內容,最終輸出的id=123。
類的其它信息
注解
// 獲取類的"annotationClass"類型的注解 (包括從基類繼承的、從接口實現的所有public成員變量)
public Annotation<A> getAnnotation(Class annotationClass)
// 獲取類的全部注解 (包括從基類繼承的、從接口實現的所有public成員變量)
public Annotation[] getAnnotations()
// 獲取類自身聲明的全部注解 (包含public、protected和private成員變量)
public Annotation[] getDeclaredAnnotations()
“父類”和“接口”相關的API
// 獲取實現的全部接口
public Type[] getGenericInterfaces()
// 獲取父類
public Type getGenericSuperclass()