Java反射机制

231 阅读4分钟

概念

Java反射(Java Reflection)是指在程序运行时获取已知类名的类或者已有对象相关信息的一种机制。包括类的方法,属性,父类等信息,还包括实例的创建和实例类型的判断等。

在一般的使用中,我们一般是显式的调用类对象及相关方法,示例代码如下:

public class Test {
    void function(){
        System.out.println("This is a function from class Test");
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.function();
    }
}

二通过反射(反过来映射),就可以根据类名来获取这个类属性和方法,也可对调用他的任意方法。

在JDK中,主要由以下类来实现Java的反射机制,这些类都在java.lang.reflect包中。

  • Class类:代表一个类
  • Constructor类:代表类的构造方法
  • Field类:代表类的成员变量
  • Method类:代表类的方法

统一形式调用

运用上述Class、Constructor、Field、Method四个类,能解析无穷多的系统类和自定义类。创建对象及方法执行等功能,而且形式都是统一的

统一形式解析类的构造方法、成员变量、成员方法

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {

    Integer property;

    public Test(){}

    public Test(Integer property){
        this.property = property;
    }

    private void function1(){
        System.out.println("This is a private function from class Test");
    }

    public void function2(){
        System.out.println("This is a public function from class Test");
    }

    public static void main(String[] args) throws ClassNotFoundException {
        //加载并初始化指定的类Test
        Class classInfo = Class.forName("Test");

        //获得类的构造函数
        System.out.println("该类的构造函数如下所示:");
        Constructor[] constructors = classInfo.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor.toString());
        }

        //获得类的所有变量
        System.out.println();
        System.out.println("该类的所有变量如下所示:");
        Field[] declaredFields = classInfo.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.toString());
        }

        //获得类的所有方法
        System.out.println();
        System.out.println("该类的所有方法如下所示:");
        Method[] declaredMethods = classInfo.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.toString());
        }
    }
}

运行结果如下:

该类的构造函数如下所示: public Test() public Test(java.lang.Integer)

该类的所有变量如下所示: java.lang.Integer Test.property

该类的所有方法如下所示: public static void Test.main(java.lang.String[]) throws java.lang.ClassNotFoundException private void Test.function1() public void Test.function2()

Test是自定义类,首先通过静态方法Class.forName("Test")返回包含Test类结构信息的Class对象classInfo,然后通过Class类中的getConstructors()方法获得Test类中的构造方法信息。通过getDeclaredField()方法获得类Test的成员变量信息,通过getDeclaredMethods()方法获得类Test的所有成员方法信息。==获得其他类的结构信息步骤与上述是相似的,所以说形式是统一的==

统一形式调用构造方法产生类的实例

import sun.nio.cs.SingleByte;

import java.lang.reflect.Constructor;

public class A {
    public A() {
        System.out.println("This is class A");
    }

    public A(Integer a){
        System.out.println("This is class A + " + a);
    }

    public A(String s,Integer m){
        System.out.println("This is class A + s:" + s+", m:"+m);
    }

    public static void main(String[] args) throws Exception{
        Class classInfo = Class.forName("A");

        //第一种方法
        Constructor[] constructors = classInfo.getConstructors();
        //调用无参构造函数
        constructors[2].newInstance();
        //调用1个参数构造函数
        //constructors[1].newInstance(new Object[]{10});
        //            ||
        constructors[1].newInstance(10);
        //调用2个参数构造函数
        //constructors[2].newInstance(new Object[]{"Hello",10});
        //            ||
        constructors[0].newInstance("Hello", 2020);

        //第二种方法
        System.out.println();
        //调用无参构造函数
        Constructor c = classInfo.getConstructor();
        c.newInstance();
        //调用1个参数构造函数
        c = classInfo.getConstructor(new Class[]{Integer.class});
        c.newInstance(new Object[]{10});
        //调用2个参数构造函数
        c = classInfo.getConstructor(new Class[]{String.class, Integer.class});
        c.newInstance(new Object[]{"Hello", 10});
    }
}

运行结果如下:

This is class A This is class A + 10 This is class A + s:Hello, m:2020

This is class A This is class A + 10 This is class A + s:Hello, m:10

可以看出,反射机制有两种对象生成实例的方法。

  • 一种是通过Class类的无参getConstructors()方法,获得Constructor对象数组。分别调用newInstance()方法,完成3个实例的创建。
  • 另一种是通过Class类的有参getConstructor()方法,来获取对应的一个构造方法信息,然后调用newInstance()方法,完成该实例的创建。

统一形式调用成员方法示例

import java.lang.reflect.Method;

public class B {
    public void func1(){
        System.out.println("This is func1");
    }

    public void func2(Integer m) {
        System.out.println("This is func2 + m:" + m);
    }

    public void func3(String s, Integer m) {
        System.out.println("This is func3 + s:" + s + ", m:" + m);
    }

    public static void main(String[] args) throws Exception {
        Class classInfo = Class.forName("B");

        //调用无惨构造方法,生成实例
        Object obj = classInfo.getConstructor().newInstance();

        //调用无惨成员方法
        Method m1 = classInfo.getMethod("func1");
        m1.invoke(obj);

        //调用有一个参数的成员方法
        Method m2 = classInfo.getMethod("func2", Integer.class);
        m2.invoke(obj,10);

        //调用有两个个参数的成员方法
        Method m3 = classInfo.getMethod("func3", String.class,Integer.class);
        m3.invoke(obj,"Hello",10);
    }
}

运行结果如下:

This is func1 This is func2 + m:10 This is func3 + s:Hello, m:10

方法反射主要是利用getMethod()方法,得到Method对象,然后利用Method类中的invoke()方法完成反射方法的执行。