Java反射机制Reflection详解
概述
Java反射机制是在运行时动态地获取一个类的信息以及针对这个类的对象操作的能力。通过反射,可以在运行时加载、探索和使用编译时已知的类。程序可以构造任意一个类的对象、获取该类中的字段、方法和构造方法、调用方法和访问/修改字段值。通过反射机制,可以在程序运行时动态地调用类的方法和字段,灵活性非常高。
获取Class对象
通过Java反射机制可以获取一个类的Class对象,而Class对象是用于获取该类的信息,如果要获取一个类的信息就需要先获得该类的Class对象。常见的方式是通过类名.class,例如:
Class<?> clazz = String.class;
还可以通过对象.getClass()方法来获取该对象对应类的Class对象,例如:
String str = "hello";
Class<?> clazz = str.getClass();
另外,还可以通过Class.forName()方法获取指定类的Class对象,例如:
Class<?> clazz = Class.forName("java.lang.String");
这种方式最常用于配置文件中指定类名字符串,然后运行时动态加载该类。
实例化对象
在获取到一个类的Class对象之后,就可以通过反射机制来实例化该类的对象了。这可以通过Class对象的newInstance()方法来实现,例如:
Class<?> clazz = String.class;
String str = (String)clazz.newInstance();
访问方法和成员变量
通过反射还可以访问类中的方法和成员变量(字段)。通过Class对象的getDeclaredMethod()方法可以获取该类中所有声明的方法,并通过Method对象来调用方法。例如:
Class<?> clazz = String.class;
Method method = clazz.getDeclaredMethod("substring", int.class, int.class);
String result = (String)method.invoke("hello world", 2, 6);
System.out.println(result); // 输出结果为 “llo w”
同样,可以通过Class对象的getDeclaredField()方法获取该类中的所有字段,并通过Field对象来访问并修改字段的值。例如:
Class<?> clazz = String.class;
Field field = clazz.getDeclaredField("value");
field.setAccessible(true); // 必须将该字段的可见性设置为true,否则会抛出IllegalAccessException异常
char[] value = (char[])field.get("hello");
value[1] = 'a';
System.out.println(new String(value)); // 输出结果为“hallo”
示例1:获取类中所有方法信息并调用指定方法
下面通过一个示例来演示如何利用Java反射机制来获取一个类中的所有方法,并调用指定方法。
我们定义一个Person类:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void sayHello() {
System.out.println("Hello, my name is " + name + ", I'm " + age + " years old.");
}
}
然后使用反射机制来获取该类中的所有方法信息,并调用指定方法:
Class<?> clazz = Person.class;
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName() + "()");
if (method.getName().equals("sayHello")) {
try {
Person p = new Person("Tom", 20);
method.invoke(p);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
输出结果:
<init>()
getName()
setName()
getAge()
setAge()
sayHello()
Hello, my name is Tom, I'm 20 years old.
该示例首先获取了Person类的Class对象,然后通过Class对象的getDeclaredMethods()方法获取该类中所有声明的方法,然后通过foreach循环遍历方法数组,并输出方法名称。在遍历过程中,如果方法名称等于“sayHello”,则实例化一个Person对象,并通过Method对象的invoke()方法来调用该方法。
示例2:通过反射机制修改数组的值
下面通过一个示例来演示如何使用反射机制来修改数组的值。
int[] array = {1, 2, 3, 4, 5};
Class<?> clazz = array.getClass();
if (clazz.isArray()) {
int length = Array.getLength(array);
for (int i = 0; i < length; i++) {
System.out.print(Array.get(array, i) + " ");
Array.set(array, i, i + 1);
}
System.out.println();
for (int i = 0; i < length; i++) {
System.out.print(Array.get(array, i) + " ");
}
}
输出结果:
1 2 3 4 5
1 2 3 4 5
该示例首先定义了一个包含5个元素的int类型数组,然后获取该数组的Class对象,并判断该Class对象是否是数组类型。如果是数组类型,则通过Array类的静态方法get()和set()来获取和设置数组中的元素的值。在遍历数组的过程中,我们将每个元素的值都加1,并输出修改后的数组的值。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java反射机制Reflection详解 - Python技术站