使用Java反射机制动态地调用方法
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
