Java 反射 参考较为官方的中英文档

203 阅读4分钟

什么是 Java 反射

具有分析类的能力的程序叫做反射;

Java 中具有分析类的能力的程序存在于 java.lang 以及 java.lang.reflect 包下面,这两个包中提供相关的类以及方法来实现反射这种思想。反射主要做的事情就是:在程序动态运行的过程当中,动态的检查以及修改类、接口、方法、字段中的内容。

对于反射的英文简单解释:

1、The java.lang and java.lang.reflect packages provide classes for java reflection.

2、Java Reflection is a process of examining or modifying the run time behavior of a class at run time.

3、The java.lang.Class class provides many methods that can be used to get metadata, examine and change the run time behavior of a class.

名字叫做 Class 的类

这个类在运行时保留有关对象和类的所有信息,而 Class 类的对象描述了特定类的属性,这个 Class 类的属性用于执行反射。

\

下文中用 Class 类 代替 名字叫做 Class 的类, 使用简称描述。

所谓名字叫做 Class 的类,放置在 JDK 的 java.lang 这个包下面,而这个类的定义如下:

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {
                                  
}                                

在 Class 类中存在非常多的静态方法,通过这些静方法的使用,可以在程序运行的时候,对开发人员编写的代码进行检查以及修改,达到反射的作用。

Class 的类的实例(也叫 Class 类对象)(或者叫做 Class 类的对象)

Class 类只是一个类,通过 Class 类可以调用一些Class 类本身的静态方法,想要调用非静态方法,需要创建 Class 对象的实例。

创建 Class 类的实例(也可以叫做 Class 类对象)可以有下面的几种方式:

1、使用 Class.forName(); 方法

public class Dog {
   Class c1 = Class.forName("Dog"); 
}

2、使用 实例.getClass(); 方法 这个方法继承于 Object 类

Dog dog = new Dog();
Class c2 = dog.getClass();

上面代码中, c2 这个 Class 类的对象是通过 dog 实例调用 getClass() 方法实现的。

3、使用 类.class;

Class c3 = Dog.class;

上述代码中, c3 这个 Class 类的对象是通过 Dog 这个类调用.class; 实现的。

使用 Class 类的反射获取接口信息

public class ReflectDemoGetInterface {
    public static void main(String[] args) {
        Dog d1 = new Dog();
 
        // 使用 d1 对象获得 Class 类,这个 Class 类中保存了 d1 对象的信息以及 创建 d1 对象的类的相关信息
        Class obj = d1.getClass();

        // 使用反射获得 d1 对象 实现的接口信息
        Class[] objInterface = obj.getInterfaces();

        for (Class c : objInterface) {
            System.out.println("实现的接口的名称是: " + c.getName());
        }
    }
}

使用 Class 类的反射获取父类以及类的访问修饰符

public class ReflectDemoGetFieldAndPublic {
    public static void main(String[] args) {
        Dog dog = new Dog();

        // 获取  Class 类的对象
        Class classObj = dog.getClass();

        // 获取 Dog 类的访问修饰符
        int modifier = classObj.getModifiers();
        System.out.println("修饰符号:" + Modifier.toString(modifier));

        // 获取 Dog 类的父类
        Class superClass = classObj.getSuperclass();
        System.out.println("super class is : " + superClass.getName());
        }
}

使用 java.lang.reflect 包下面的相关类以及方法反射获取类中字段、方法以及构造函数

测试需要的代码

Animal 接口

interface Animal {
    void display();
}

Mammal 接口

public interface Mammal {
    void makeSound();
}

Dog 类

public class Dog implements Animal, Mammal{
    public String type;
    private String color;

    @Override
    public void display() {
        System.out.println("this is a dog...");
    }

    @Override
    public void makeSound() {
        System.out.println("dog is backing...");
    }

    protected void eat() {
        System.out.println("dog is eating...");
    }

    public Dog(String type) {
        this.type = type;
    }

    public Dog() {

    }

    public Dog(String type, String color) {
        this.type = type;
        this.color = color;
    }
}

获取字段以及字段修饰符

 public static void main(String[] args) {
     Dog d1 = new Dog();

     Class obj = d1.getClass();

     try {
         Field field1 = obj.getField("type");
         field1.set(d1, "Hello type has been changed");
         String typeValue = (String) field1.get(d1);
         System.out.println("type : " + typeValue);

         /**
             * 获取类型的访问修饰符
             */
         int mod1 = field1.getModifiers();
         String modifier1 = Modifier.toString(mod1);
         System.out.println("字段的修饰符是: " + modifier1);
         System.out.println("");
     } catch (NoSuchFieldException e) {
         e.printStackTrace();
     } catch (IllegalAccessException e) {
         e.printStackTrace();
     }
 }

获取私有字段

/**
* 利用反射访问私有字段
*/
public static void testPrivateField() {
    try {
        Dog d1 = new Dog();
        Class obj = d1.getClass();
        Field field2 = obj.getDeclaredField("color");
        field2.setAccessible(true);
        field2.set(d1, "Blue");
        String colorValue = (String) field2.get(d1);
        System.out.println("利用反射获取到的私有字段的颜色是: " + colorValue);
        System.out.println("");
    } catch (Exception e) {
        e.printStackTrace();
    }
}

获取方法以及方法的修饰符

public static void testPublicMethod() {
    try {
        // 创建动物对象
        Dog d1 = new Dog();

        // 使用动物对象获取到 Class 对象
        // Class 对象中保留了有关类以及对象的所有信息 d1 的 Class 对象中保存了 Dog 类以及 Dog 类创建出来的对象的所有信息
        Class obj = d1.getClass();

        // 使用 Class 对象,调用实例方法,得到相关类的方法信息
        Method[] method = obj.getDeclaredMethods();
        for (Method m : method) {
            System.out.println("方法名称是: " + m.getName());

            // 获取修饰方法的修饰符 public protected default private 四种修饰符号
            int modifier = m.getModifiers();
            System.out.println("方法的修饰符是: " + Modifier.toString(modifier));

            // 获取方法的返回值类型
            System.out.println("Return Types: " + m.getReturnType());
            System.out.println("");
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

\

获取构造方法

public static void testReflectConstructor() {
    try {
        Dog dog = new Dog();
        Class obj = dog.getClass();

        Constructor[] constructor = obj.getDeclaredConstructors();

        for (Constructor c : constructor) {
            System.out.println("构造函数的名字是: " + c.getName());
            int modifier = c.getModifiers();
            System.out.println("构造方法的修饰符是:" + Modifier.toString(modifier));
            System.out.println("构造函数中参数的个数: " + c.getParameterCount());
            System.out.println("");
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

小结

本文介绍了 Java 反射的相关概念,以及使用 Class 类与 java.lang.reflect 包下面的相关类实现了动态的对于类、接口、方法、字段的检查以及修改,加深了对于 Java 反射的理解。需要注意的是 反射 是一种思想,在 Spring 等框架中有大量使用,这种反射思想在 JDK 不同包下面的不同类相互协作下实现的,反射的主要实现方法是在 java.lang.reflect 包中实现的。

参考

Java 反射 Reflection

Java Reflection

Java Reflection and Class