前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JDK源码分析 反射

JDK源码分析 反射

作者头像
Yano_nankai
发布2018-10-08 10:37:44
4080
发布2018-10-08 10:37:44
举报
文章被收录于专栏:二进制文集二进制文集

说明

对于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()
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.08.07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 说明
  • 反射简介
    • 类的部分已知的信息:
      • 类的全部信息
      • 根据类名构造类
        • 代码示例
          • User类
      • 获取 class 对象
      • class 的 API
        • 构造函数
          • 成员方法
            • 成员变量
              • 类的其它信息
                • 注解
                • “父类”和“接口”相关的API
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档