反射-类的秘密,你全都知道

44 阅读2分钟

定义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

例如:一个类有:成员变量、方法、构造方法等等信息,利用反射技术可以对一个类进行拆分,组成部分映射成一个个对象。

回顾Class对象生成

类加载进JVM的时候,三个步骤:

  1. 通过全限定类名获取该类的二进制的字节流
  2. 将静态的存储结构变成方法区运行时的数据结构
  3. 生成java.lang.Class对象,作为方法区这个类的各种数据结构访问入口

反射的使用

Class类

  • 根据类名:类名.class
  • 根据对象:对象.getClass()
  • 根据全限定类名:Class.forName(全限定类名)
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    //类名.class
    Class<String> stringClass = String.class;
    //对象.getClass()
    String str = "abc";
    Class<? extends String> aClass = str.getClass();
    //全限定类名
    Class<?> clazz = Class.forName("java.lang.String");

    //实例化类
    Object o = clazz.newInstance();
}

Constructor类

Constructor类存在于反射包(java.lang.reflect)中,反映的是Class 对象所表示的类的构造方法。

public static void main(String[] args) throws Exception {

    Class<?> clazz = Class.forName("com.juejin.Student");

    //默认构造方法 Student必须包含无参构造
    Student student = (Student) clazz.newInstance();
    student.setAge(18);
    student.setName("弥金");

    //指定参数类型构造方法
    Constructor<?> constructor = clazz.getConstructor(int.class, String.class);
    //private必须设置为可访问
    constructor.setAccessible(true);
    constructor.newInstance(18, "弥金");

    //获取所有构造方法
    Annotation[] declaredAnnotations = clazz.getDeclaredAnnotations();

}

Field类

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。

public static void main(String[] args) throws Exception {

    Class<?> clazz = Class.forName("com.juejin.Student");

    //public修饰符(注意字段必须存在)
    Field field = clazz.getField("name");
    //任意修饰符(注意字段必须存在)
    Field declaredField = clazz.getDeclaredField("age");

    //获取所有字段(包括私有的)
    Field[] declaredFields = clazz.getDeclaredFields();
    //获取所有字段(仅public)
    Field[] fields = clazz.getFields();

    //浅浅赋值一下
    Student student = (Student) clazz.newInstance();
    declaredField.setAccessible(true);
    declaredField.set(student, 18);
}

Method类

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息,所反映的方法可能是类方法或实例方法(包括抽象方法)。

public static void main(String[] args) throws Exception {

    Class<?> clazz = Class.forName("com.juejin.Student");
    Student student = (Student) clazz.newInstance();
    student.setAge(18);

    //获取所有public的方法
    Method[] methods = clazz.getMethods();
    //获取当前类的方法(包含private),无法获取继承自父类的方法哦
    Method[] declaredMethods = clazz.getDeclaredMethods();
    //获取具体的方法
    Method getAge = clazz.getDeclaredMethod("getAge");
    
    //浅浅地调用一下
    getAge.setAccessible(true);
    Object invoke = getAge.invoke(student);
    System.out.println(invoke);
}