Java之反射

1.什么是反射

运行状态中, 能够动态的获取以及调用对象的信息

类加载区别

2.Class文件包含的内容

Class文件包含的内容

3.反射关键类图

反射关键类图

  1. Member: 有关单个成员(字段或方法)或构造函数的标识信息的接口
  2. AccessibleObject: FieldMethodConstructor对象的基类(在反射对象中设置accessible标志允许具有足够特权)
  3. Field: 提供有关类或接口的单个​​字段的信息和动态访问, 包括类(静态)字段、实例字段
  4. Executable: MethodConstructor通用功能的超类
  5. Method: 提供有关类或接口上的单个方法的信息和对其的访问, 包含类方法、实例方法(抽象方法)
  6. Constructor<T>: 提供有关类的单个构造函数的信息和对其的访问

4.基础应用

1.获取Class对象的方式:

  1. Class.forName()
Class<String> clazz = (Class<String>) Class.forName("java.lang.String");
  1. 对象.class
Class<String> clazz = String.class;
  1. 对象实例.getClass()
Class<String> clazz = (Class<String>) "".getClass();

2.生成实例

// 普通生成实例
String str = new String();

// 反射生成实例
// 1. 获取Class对象
Class<String> clazz = (Class<String>) Class.forName("java.lang.String");
// 2. 获取构造函数对象
Constructor<String> constructor = clazz.getConstructor();
// 3. 获取实例
String str = constructor.newInstance();

生成对象步骤

3.获取对象信息
例如: 存在一个Person类

public class Person {

        public Person(int age, String name) {
            this.age = age;
            this.name = name;
        }

        public int age;

        private String name;

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
  1. 获取Person对象
Class<Person> clazz = Person.class;
// 因为Person只有有参构造, 所以这边同样使用了有参
Constructor<Person> constructor = clazz.getConstructor(int.class, String.class);
Person person = constructor.newInstance(18, "反射");
  1. 成员变量
Field ageField = clazz.getField("age");
int age1 = (int) ageField.get(person);
// age1: 18
System.out.println(age1);
// name是由private修饰, 直接使用getField()方法获取失败
// Field nameField = clazz.getField("name");
// 此设置无效: 因为在程序走到此步前, 已经返回NoSuchFieldException错误
// nameField.setAccessible(true);
Field nameDeclaredField = clazz.getDeclaredField("name");
// 关键一步: 获取访问权限, 如缺失, 则依旧访问失败
nameDeclaredField.setAccessible(true);
String name = (String) nameDeclaredField.get(person);
// name: 反射
System.out.println(name);
  1. 函数
// 对于private修饰的方法, 同成员变量的规则
Method setAge = clazz.getMethod("setAge", int.class);
setAge.invoke(person, 20);
Method getAge = clazz.getMethod("getAge");
int age2 = (int) getAge.invoke(person);
// age2: 20(18 -> 20)
System.out.println(age2);

总结

getxx: 能访问使用public修饰的, 并且包括超类的所有信息
getDeclaredxx: 只能访问本类的所有信息

  • public: getxxgetDeclaredxx都行

  • protected: getDeclaredxx就行

  • default(无): getDeclaredxx就行

  • private: getDeclaredxx同时需设置xx.setAccessible(true)

  • 正常使用时: 可直接使用getDeclaredxx + xx.setAccessible(true)进行操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值