介绍

java反射可以在运行时获取对象的成员和属性, 并且可以动态的创建对象并调用对象的属性.
反射一般编程中很少使用,但是在很多框架中都使用了反射, 比如配置Spring的Xml配置文件中, 就使用全类名配置方式, 其实就是反射的一种使用方式.

同时反射对单例模式有一定的影响, 可以参考反射获取单例对象

获取反射对象

获取反射Class对象一共三种方式

1
2
3
4
5
6
7
// 1. 使用实例获取
User user = new User();
Class<? extends User> aClass = user.getClass();
// 2. 使用类获取
Class<User> userClass = User.class;
// 3. 全类名获取, 可能会抛出 ClassNotFoundException 异常
Class<?> aClass1 = Class.forName("com.liuzhihang.tool.reflect.User");

获取属性

  1. 获取字段
    1
    2
    3
    4
    5
    6
    7
    8
    // 获取所有公有字段 (public)
    Field[] fields = aClass.getFields();
    // 获取所有字段 (public 缺省, protected, private)
    Field[] fields = aClass.getDeclaredFields()
    // 获取指定公共字段
    Field age = aClass.getField("age");
    // 获取指定字段 (public 缺省, protected, private)
    Field userName = aClass.getDeclaredField("userName");

获取构造

  1. 获取构造
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 获取所有构造 不能获取私有
    Constructor<?>[] constructors = aClass.getConstructors();

    // 获取指定参数类型的构造 不能获取私有 空则获取空参构造 getConstructor(Class<?>... parameterTypes)
    Constructor<User> constructor = aClass.getConstructor(String.class);

    // 获取所有构造 包含私有
    Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();

    // 获取指定参数类型的构造 可以获取私有 空则获取空参构造 getDeclaredConstructor(Class<?>... parameterTypes)
    Constructor<User> declaredConstructor = aClass.getDeclaredConstructor(String.class);

  2. 使用构造创建对象

可以通过 constructor.setAccessible(true); 暴力破解忽略访问修饰符, 来使用私有构造参数

1
2
3
4
5
6
Constructor<User> constructor = aClass.getDeclaredConstructor(String.class);
// 暴力破解
constructor.setAccessible(true);

User test = constructor.newInstance("test");

获取方法

  1. 获取方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 获取所有公共方法(包含父类)
    Method[] methods = aClass.getMethods();
    // 获取所有方法
    Method[] methods = aClass.getDeclaredMethods();
    // 获取私有方法 第一个参数填方法名称
    Method address = aClass.getDeclaredMethod("setAddress", String.class);
    // 获取公共方法
    Method address = aClass.getMethod("setAddress", String.class);

  2. 使用方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    Class<?> aClass = Class.forName("com.liuzhihang.tool.reflect.User")

    Method address = aClass.getDeclaredMethod("setAddress", String.class);

    User user = aClass.getConstructor().newInstance();

    System.out.println(user.toString());
    // 解除私有限制
    address.setAccessible(true);
    // 使用invoke来调用方法
    address.invoke(user, "北京");

    System.out.println(user.toString());

获取其他属性

还可以获取类实现的接口, 父类, 注解, 以及判断类的类型等多种使用方式.