Java核心技术【二十六】Java 反射详解(基于 JDK 17)
在 Java 编程中,反射是一种强大的机制,它允许程序在运行时动态地获取类的信息、访问对象的属性和方法、创建对象等。对于初学者来说,理解反射可能会有一定的挑战,但它也是掌握 Java 高级特性的重要一步。
一、什么是反射
反射(Reflection)是指在程序运行时,能够获取一个对象所属的类信息,包括类的名称、属性、方法、构造函数等,并且可以通过这些信息来操作对象。简单来说,反射就是让程序能够 “自我审视” 和 “自我操作”。
二、反射的作用
1. 动态创建对象
在某些情况下,我们可能不知道要创建的对象的具体类型,只知道类的名称。通过反射,可以根据类名动态地创建对象。
2. 访问和修改对象的属性
反射可以让我们在运行时访问和修改对象的私有属性,这在一些需要动态配置的场景中非常有用。
3. 调用对象的方法
可以根据方法名和参数类型在运行时调用对象的方法,而不需要在编译时就确定方法的调用。
三、反射的基本用法
(一)获取类对象
首先,定义一个测试类 MyClass:
package java_core_26;
public class MyClass{
private static final long serialVersionUID = 1L;
private String name = "小明";
private String addr = "北京";
public String getAll(String all) {
return all + name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public MyClass(String name, String addr) {
super();
this.name = name;
this.addr = addr;
}
public MyClass() {
super();
// TODO Auto-generated constructor stub
}
}
在 Jdk 17 中,要使用反射,首先需要获取一个类的对象。有三种方式可以获取类对象:
1. 使用类名.class
这种方式在编译时就确定了类的类型,比较安全:
Class<?> clazz = MyClass.class;
2. 使用对象的 getClass () 方法
这种方式通过已经创建的对象来获取类对象:
MyClass obj = new MyClass();
Class<?> clazz = obj.getClass();
3. 使用 Class.forName () 方法
这种方式需要传入类的全限定名,在运行时加载类。如果类找不到,会抛出 ClassNotFoundException。
try {
Class<?> clazz = Class.forName("java_core_26.MyClass");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
(二)创建对象
获取了类对象之后,可以通过反射来创建对象。在 JDK 17 使用 getConstructor() 方法获取无参构造函数,然后通过构造函数的 newInstance() 方法创建对象。如果类没有无参构造函数,或者构造函数不可访问,会抛出相应的异常。
public class Test {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("java_core_26.MyClass");
// 获取无参构造函数
var constructor = clazz.getConstructor();
// 使用构造函数创建对象
Object obj = constructor.newInstance();
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
(三)访问属性
反射可以让我们访问对象的私有属性。在 JDK 17 中,可以使用以下方式访问属性:
public class Test {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("java_core_26.MyClass");
// 获取无参构造函数
var constructor = clazz.getConstructor();
// 使用构造函数创建对象
Object obj = constructor.newInstance();
// 获取私有属性 addr
Field field = clazz.getDeclaredField("addr");
// 允许访问私有属性
field.setAccessible(true);
// 设置属性值
field.set(obj, "new value");
// 获取属性值
Object value = field.get(obj);
System.out.println(value);
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException |
IllegalAccessException | InvocationTargetException | NoSuchFieldException |
SecurityException e) {
e.printStackTrace();
}
}
}
在上面的代码中,getDeclaredField() 方法获取 MyClass 的私有属性 addr,setAccessible(true) 设置属性可访问,然后通过 set() 和 get() 方法设置和获取属性的值。
(四)调用方法
反射也可以用来调用对象的方法。在 JDK 17 中,可以使用以下方式调用方法:
package java_core_26;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class Test {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("java_core_26.MyClass");
// 获取无参构造函数
var constructor = clazz.getConstructor();
// 使用构造函数创建对象
Object obj = constructor.newInstance();
// 获取方法
var method = clazz.getMethod("getAll", String.class);
// 调用方法
Object result = method.invoke(obj, "小李");
System.out.println(result);
} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException |
IllegalAccessException | InvocationTargetException |
SecurityException e) {
e.printStackTrace();
}
}
}
在上面的代码中,getMethod() 方法获取公共方法,传入方法名和参数类型。然后通过 invoke() 方法调用方法,传入对象和参数。如果方法有返回值,可以获取返回值。
四、反射的注意事项
1. 性能问题
反射的性能相对较低,因为它需要在运行时进行类型检查和方法调用。在性能敏感的代码中,应尽量避免频繁使用反射。
2. 安全限制
反射可以访问和修改私有属性和方法,但这可能会破坏封装性。在某些安全敏感的环境中,可能需要限制反射的使用。
3. 异常处理
使用反射时,可能会抛出各种异常,如 ClassNotFoundException、NoSuchMethodException、InstantiationException、IllegalAccessException、InvocationTargetException 等。在代码中需要进行适当的异常处理,以确保程序的稳定性。
五、总结
反射是 Java 中一种强大的机制,它允许程序在运行时动态地获取类的信息、访问对象的属性和方法、创建对象等。在 JDK 17 中,反射的基本用法与之前版本类似,但也有一些细微的变化。对于初学者来说,理解反射的基本概念和用法,可以帮助更好地理解 Java 的高级特性。在使用反射时,需要注意性能问题、安全限制和异常处理,以确保程序的正确性和稳定性。
遇见即是缘分,关注🌟、点赞👍、收藏📚,让这份美好延续下去!
🌟 对技术管理感兴趣 请关注 ⬇ 【 技术管理修行】