[关闭]
@Yano 2017-08-07T08:50:59.000000Z 字数 4903 阅读 1887

JDK源码分析 反射

Java


说明

对于JDK源码分析的文章,仅仅记录我认为重要的地方。源码的细节实在太多,不可能面面俱到地写清每个逻辑。所以我的JDK源码分析,着重在JDK的体系架构层面,具体源码可以参考:http://www.cnblogs.com/skywang12345/category/455711.html

反射简介

在运行状态中,我们可以根据“类的部分已知的信息”来还原“类的全部的信息”。

类的部分已知的信息:

类的全部信息

根据类名构造类

代码示例

User类

  1. public class User implements Serializable{
  2. private static final long serialVersionUID = 1510634274152200118L;
  3. private int id;
  4. private String passWord;
  5. public User() {
  6. System.out.println("Create user... ");
  7. }
  8. public User(int id, String passWord) {
  9. this.id = id;
  10. this.passWord = passWord;
  11. }
  12. public int getId() {
  13. return id;
  14. }
  15. public void setId(int id) {
  16. this.id = id;
  17. }
  18. public String getPassWord() {
  19. return passWord;
  20. }
  21. public void setPassWord(String passWord) {
  22. this.passWord = passWord;
  23. }
  24. @Override
  25. public String toString() {
  26. return "User [id=" + id + ", passWord=" + passWord + "]";
  27. }
  28. }

根据类名,构造类的代码:

  1. @Test
  2. public void testReflection() throws Exception {
  3. Class<?> clazz = Class.forName("test.User");
  4. User user = (User) clazz.newInstance();
  5. System.out.println("user = " + user);
  6. }

输出:

Create user... 
user = User [id=0, passWord=null]

获取 class 对象

  1. @Test
  2. public void testClazz() throws Exception {
  3. Class<?> clazz1 = Class.forName("test.User");
  4. Class clazz2 = User.class;
  5. Class clazz3 = new User().getClass();
  6. System.out.println("clazz1: " + clazz1);
  7. System.out.println("clazz2: " + clazz2);
  8. System.out.println("clazz3: " + clazz3);
  9. }

输出:

Create user... 
clazz1: class test.User
clazz2: class test.User
clazz3: class test.User

class 的 API

构造函数

  1. // 获取“参数是parameterTypes”的public的构造函数
  2. public Constructor getConstructor(Class[] parameterTypes)
  3. // 获取全部的public的构造函数
  4. public Constructor[] getConstructors()
  5. // 获取“参数是parameterTypes”的,并且是类自身声明的构造函数,包含public、protected和private方法。
  6. public Constructor getDeclaredConstructor(Class[] parameterTypes)
  7. // 获取类自身声明的全部的构造函数,包含public、protected和private方法。
  8. public Constructor[] getDeclaredConstructors()
  9. // 如果这个类是“其它类的构造函数中的内部类”,调用getEnclosingConstructor()就是这个类所在的构造函数;若不存在,返回null。
  10. public Constructor getEnclosingConstructor()

测试:

  1. @Test
  2. public void testConstructor() throws Exception {
  3. Class<?> clazz = Class.forName("test.User");
  4. Constructor<?> constructor = clazz.getDeclaredConstructor(null);
  5. Object object1 = constructor.newInstance();
  6. System.out.println(object1);
  7. Constructor<?> constructor2 = clazz.getDeclaredConstructor(new Class[] {int.class, String.class});
  8. Object object2 = constructor2.newInstance(1, "123456");
  9. System.out.println(object2);
  10. }

输出:

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;
}

成员方法

  1. // 获取“名称是name,参数是parameterTypes”的public的函数(包括从基类继承的、从接口实现的所有public函数)
  2. public Method getMethod(String name, Class[] parameterTypes)
  3. // 获取全部的public的函数(包括从基类继承的、从接口实现的所有public函数)
  4. public Method[] getMethods()
  5. // 获取“名称是name,参数是parameterTypes”,并且是类自身声明的函数,包含public、protected和private方法。
  6. public Method getDeclaredMethod(String name, Class[] parameterTypes)
  7. // 获取全部的类自身声明的函数,包含public、protected和private方法。
  8. public Method[] getDeclaredMethods()
  9. // 如果这个类是“其它类中某个方法的内部类”,调用getEnclosingMethod()就是这个类所在的方法;若不存在,返回null。
  10. public Method getEnclosingMethod()

可以判断类中是否含有某个方法,也可以调用类中的任何一个方法(包括私有方法)。

  1. @Test
  2. public void testMethod() throws Exception {
  3. Class<?> clazz = Class.forName("test.User");
  4. Method[] declaredMethods = clazz.getDeclaredMethods();
  5. for (Method method : declaredMethods) {
  6. System.out.println(method);
  7. }
  8. System.out.println();
  9. Method printInfo = clazz.getDeclaredMethod("printInfo", new Class[]{});
  10. User user = (User) clazz.newInstance();
  11. printInfo.invoke(user, null);
  12. }

输出:

  1. Create user...
  2. public java.lang.String test.User.toString()
  3. public int test.User.getId()
  4. public void test.User.printInfo()
  5. public void test.User.setId(int)
  6. public void test.User.setPassWord(java.lang.String)
  7. public java.lang.String test.User.getPassWord()
  8. User [id=0, passWord=null]

成员变量

  1. // 获取“名称是name”的public的成员变量(包括从基类继承的、从接口实现的所有public成员变量)
  2. public Field getField(String name)
  3. // 获取全部的public成员变量(包括从基类继承的、从接口实现的所有public成员变量)
  4. public Field[] getFields()
  5. // 获取“名称是name”,并且是类自身声明的成员变量,包含public、protected和private成员变量。
  6. public Field getDeclaredField(String name)
  7. // 获取全部的类自身声明的成员变量,包含public、protected和private成员变量。
  8. public Field[] getDeclaredFields()
  1. @Test
  2. public void testField() throws Exception {
  3. Class<?> clazz = Class.forName("test.User");
  4. Field[] fields = clazz.getDeclaredFields();
  5. for (Field field : fields) {
  6. System.out.println(field);
  7. }
  8. // 创建并通过反射,修改一个 private 变量 id
  9. User user = (User) clazz.newInstance();
  10. Field field = clazz.getDeclaredField("id");
  11. field.setAccessible(true);
  12. field.set(user, 123);
  13. user.printInfo();
  14. }

输出:

  1. private static final long test.User.serialVersionUID
  2. private int test.User.id
  3. private java.lang.String test.User.passWord
  4. Create user...
  5. User [id=123, passWord=null]

我们可以看到,User中对于id的定义:

private int id;

而在测试用例中,可以获取对象中私有的id变量,并直接修改内容,最终输出的id=123。

类的其它信息

注解

  1. // 获取类的"annotationClass"类型的注解 (包括从基类继承的、从接口实现的所有public成员变量)
  2. public Annotation<A> getAnnotation(Class annotationClass)
  3. // 获取类的全部注解 (包括从基类继承的、从接口实现的所有public成员变量)
  4. public Annotation[] getAnnotations()
  5. // 获取类自身声明的全部注解 (包含public、protected和private成员变量)
  6. public Annotation[] getDeclaredAnnotations()

“父类”和“接口”相关的API

  1. // 获取实现的全部接口
  2. public Type[] getGenericInterfaces()
  3. // 获取父类
  4. public Type getGenericSuperclass()
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注