欢迎访问宙启技术站
智能推送

使用Java反射机制动态地调用方法

发布时间:2023-05-30 06:56:23

Java反射机制是Java中的一个很重要的特性,它允许程序在运行时获取类的信息,并可以动态的调用类中的方法、操作类属性、实例化对象等。Java反射机制可以在框架、注解、代理等方向上有大量应用,能够提高程序的扩展性和灵活性,是Java语言中非常重要的一个部分。下面我们将通过一个示例来学习Java反射机制的基础使用,我们将会学习如下内容:

1. 获取Class对象;

2. 通过Class对象实例化对象;

3. 调用对象的方法;

4. 获取类的方法信息;

5. 调用指定的方法。

本文假设你已经掌握基础的Java语言知识和一定的面向对象编程思想。

一、获取Class对象

在Java中,我们可以通过Class类来获取某个类的相关信息,比如构造函数、方法、变量等信息。获取Class对象的方式有很多种,下面我们介绍以下几种:

1. 通过对象的getClass()方法获取

在Java中,每个对象都有一个getClass()方法,通过这个方法可以获取该对象的Class对象。例如:

public class Main {
    public static void main(String[] args) {
        String str = "Hello World";
        Class strClass = str.getClass(); // 获取String类的Class对象
        System.out.println(strClass.getName()); // 输出类名
    }
}

输出结果:java.lang.String

2. 通过类名.class获取

如果已知类名,也可以通过类名.class来获取该类对应的Class对象。例如:

public class Main {
    public static void main(String[] args) {
        Class strClass = String.class; // 获取String类的Class对象
        System.out.println(strClass.getName()); // 输出类名
    }
}

输出结果:java.lang.String

3. 通过Class的静态方法forName()获取

通过Class的静态方法forName()可以根据类的全限定名来获取该类对应的Class对象。例如:

public class Main {
    public static void main(String[] args) throws ClassNotFoundException {
        Class strClass = Class.forName("java.lang.String"); // 获取String类的Class对象
        System.out.println(strClass.getName()); // 输出类名
    }
}

输出结果:java.lang.String

二、通过Class对象实例化对象

获取类的Class对象后,我们可以实例化对象。Java反射机制提供了很多实例化对象的方法,下面我们介绍以下几种:

1. 通过Class的newInstance()方法实例化对象

这是最基本的实例化对象的方法,我们可以通过Class的newInstance()方法来实例化对象。前提条件是该类必须有一个无参构造函数。

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class strClass = Class.forName("java.lang.String"); // 获取String类的Class对象
        String str = (String) strClass.newInstance(); // 实例化对象
        System.out.println(str); // 输出对象
    }
}

输出结果:null

2. 通过Constructor的newInstance()方法实例化对象

Constructor是一个专门用来描述类的构造函数信息的类,我们可以通过Constructor来获取构造函数,并实例化对象。Constructor有一个newInstance()方法,可以实例化对象。

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class strClass = Class.forName("java.lang.String"); // 获取String类的Class对象
        Constructor constructor = strClass.getConstructor(); // 获取String类的无参构造函数
        String str = (String) constructor.newInstance(); // 实例化对象
        System.out.println(str); // 输出对象
    }
}

输出结果:null

这里需要注意的是,如果该类没有无参构造函数,需要传递构造函数的参数类型及参数。例如:

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

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class personClass = Class.forName("Person"); // 获取Person类的Class对象
        Constructor constructor = personClass.getConstructor(String.class, int.class); // 获取Person类的构造函数
        Person person = (Person) constructor.newInstance("Tom", 20); // 实例化对象
        System.out.println(person); // 输出对象
    }
}

输出结果:Person{name='Tom', age=20}

三、调用对象的方法

获取对象后,我们可以调用对象的方法。Java反射机制提供了许多方法用于调用对象的方法,下面我们介绍几种方法:

1. 通过Method的invoke()方法调用对象的方法

Method是一个专门用来描述类的方法信息的类,我们可以通过Method来获取方法,并调用方法。Method有一个invoke()方法,可以调用对象的方法。

public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void sayHello() {
        System.out.println("Hello, my name is " + this.name);
    }
    public void sayAge() {
        System.out.println("My age is " + this.age);
    }
}

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class personClass = Class.forName("Person"); // 获取Person类的Class对象
        Constructor constructor = personClass.getConstructor(String.class, int.class); // 获取Person类的构造函数
        Person person = (Person) constructor.newInstance("Tom", 20); // 实例化对象
        Method sayHelloMethod = personClass.getMethod("sayHello"); // 获取sayHello方法信息
        Method sayAgeMethod = personClass.getMethod("sayAge"); // 获取sayAge方法信息
        sayHelloMethod.invoke(person); // 调用对象的sayHello方法
        sayAgeMethod.invoke(person); // 调用对象的sayAge方法
    }
}

输出结果:

Hello, my name is Tom

My age is 20

2. 通过反射获取属性并操作属性

除了调用对象的方法,Java反射机制还提供了获取属性的方法,可以对属性进行操作。下面是一个示例:

public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void sayHello() {
        System.out.println("Hello, my name is " + this.name);
    }
    public void sayAge() {
        System.out.println("My age is " + this.age);
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return this.age;
    }
}

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        Class personClass = Class.forName("Person"); // 获取Person类的Class对象
        Constructor constructor = personClass.getConstructor(String.class, int.class); // 获取Person类的构造函数
        Person person = (Person) constructor.newInstance("Tom", 20); // 实例化对象
        Field nameField = personClass.getDeclaredField("name"); // 获取name属性信息
        Field ageField = personClass.getDeclaredField("age"); // 获取age属性信息
        nameField.setAccessible(true); // 将private的属性设置为可访问
        ageField.setAccessible(true); // 将private的属性设置为可访问
        System.out.println(nameField.get(person)); // 获取name属性的值
        System.out.println(ageField.get(person)); // 获取age属性的值
        nameField.set(person, "Jerry"); // 设置name属性的值
        ageField.set(person, 30); // 设置age属性的值
        System.out.println(nameField.get(person)); // 获取name属性的值
        System.out.println(ageField.get(person)); // 获取age属性的值
    }
}

输出结果:

Tom

20

Jerry

30