java 反射

1, Class 可以理解是字节码对象

2, 不使用源码获取到类的信息, 比如方法, 成员变量等

获取的途径

下面三种效果是一样的, 只是泛型不一样

// 1, 类.class
Class<User> userCls = User.class;
// 2, 对象.getClass()
Class<? extends User> userCls2 = new User().getClass();
// 3, Class.forName("类的全路径")
Class<?> userCls3 = Class.forName("com.study.User");

获取构造方法

// 获取所有构造方法
Constructs[] constructors = User.getConstructors();
// 获取具体构造方法
User user = new User();
Constructor<User> constructor = userCls1.getConstructor(String.class, int.class);

创建对象(执行构造方法)

// 执行一个有参的构造方法创建对象
User user = constructor.newInstance("Marry", 20);
// 执行无参的构造创建对象, 如果是无参构造, 可以省去获取构造方法这一步骤
User user2 = User.class.newInstance()

获取字段

Class<User> userCls = User.class;
// 获取所有字段, 返回一个字段数组
Field[] fields = userCls.getDeclaredFields();
for (Field f : fields) {
    String fieldName = f.getName();
    System.out.println(fieldName);
}
// 获取指定的字段
Field field = userCls.getField("name");

获取字段值

// 获取构造方法
Constructor<User> constructor = userCls1.getConstructor(String.class, int.class);
// 创建一个对象
User user = constructor.newInstance("Marry", 20);
// 获取指定的字段
Field field = User.class.getDeclaredField("username");
// 暴力反射, 用于获取非公开变量
field.setAccessible(true);
// 指明获取字段值的目标对象
String username = (String) field.get(user);
System.out.println(username);

设置/修改字段值

// 获取构造方法
Constructor<User> constructor = userCls1.getConstructor(String.class, int.class);
// 创建一个对象
User user = constructor.newInstance("Marry", 20);
// 获取指定的字段
Field field = User.class.getDeclaredField("username");
// 只是设置不需要暴力反射, 获取需要, 既获取又设置也需要
field.setAccessible(true);
// 设置新的值, 原本是 Marry
field.set(user, "Bob");
// 获取
String username = (String) field.get(user);
System.out.println(username);

获取类的方法

// 获取所有方法
Method[] methods = User.class.getDeclaredMethods();
// 获取指定方法
Method method = User.class.getMethod("setUsername", String.class);
// 获取 Stirng 类的 replaceAll 方法
Method method2 = String.class.getMethod("replaceAll", String.class, String.class);

执行方法

// 执行方法, 也需要指明对象, 第一个参数是目标对象, 第二个参数是执行方法的参数
method.invoke(user, "Rose");
// 如果是私有方法需要放开权限(暴力反射)
method.setAccessible(true);
// 参数可以是可变参数, 也可以是数组: "hello word".replaceAll("o", "a")
String str2 = (String) method2.invoke("hello word", "o", "a");

 

posted @ 2018-10-21 19:51  huanggy  阅读(216)  评论(0编辑  收藏  举报