456. Java 反射 - 浅层方法访问
在前面的课程中,我们学习了如何获取对象的 Class,现在我们来探索 如何通过 Reflection 获取类的方法,并调用它们。
1. 查看类的所有方法
我们可以使用 Class.getMethods() 获取某个类的 所有公共方法(包括继承的接口方法和父类方法):
import java.util.Iterator;
import java.util.stream.Stream;
public class MethodsOnIterator {
public static void main(String[] args) {
Stream.of(Iterator.class.getMethods())
.forEach(System.out::println);
}
}
输出示例(以 Java 21 为例):
public default void java.util.Iterator.remove()
public default void java.util.Iterator.forEachRemaining(java.util.function.Consumer)
public abstract boolean java.util.Iterator.hasNext()
public abstract java.lang.Object java.util.Iterator.next()
✅ 说明:
- 可以看到迭代器的方法包括抽象方法和默认方法
- Reflection 可以让我们在运行时访问这些方法,并调用它们
2. 通过 Reflection 调用方法
假设我们想调用 Iterator 的 forEachRemaining 方法:
import java.util.List;
import java.util.Iterator;
import java.util.function.Consumer;
public class MethodsOnIteratorCalling {
public static void main(String[] args) throws ReflectiveOperationException {
// 创建一个迭代器
Iterator<String> iterator = Arrays.asList("Hello", "Dev", "Java").iterator();
// 1. 获取 forEachRemaining 方法
// 注意:需要指定参数类型的 Class 对象
Method forEachRemainingMethod = Iterator.class.getMethod("forEachRemaining", Consumer.class);
// 2. 准备参数:定义一个 Consumer 用于打印
Consumer<String> println = System.out::println;
// 3. 调用方法
// invoke(对象实例, 参数...)
forEachRemainingMethod.invoke(iterator, println);
}
}
✅ 注意事项:
- 可能会抛出异常,如
NoSuchMethodException或IllegalAccessException - Java 7 引入
ReflectiveOperationException,覆盖了所有反射相关异常
3. 动态调用静态方法
Reflection 还可以用来 动态调用静态方法,即使我们在编写代码时并不知道具体方法。下面是一个实战示例:
3.1 目标
- 对一个数字列表进行操作
- 在
Collections类中查找所有返回类型为void、参数为List的方法 - 调用这些方法并观察效果
3.2 示例代码
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class CollectionsListMethods {
public static void main(String[] args) throws ReflectiveOperationException {
// 1. 准备数据:将 π 的前 16 位数字拆分为 List<Integer>
String piStr = "3141592653589793";
List<Integer> pi = piStr.chars()
.map(c -> c - '0')
.boxed()
.collect(Collectors.toList());
System.out.println("原始列表: " + pi);
// 2. 遍历 Collections 的所有公共方法
for (Method method : Collections.class.getMethods()) {
// 筛选条件:
// 1. 返回值为 void
// 2. 参数个数为 1
// 3. 参数类型为 List
if (method.getReturnType() == void.class
&& method.getParameterCount() == 1
&& method.getParameterTypes()[0] == List.class) {
System.out.println("调用方法: " + method.getName());
// 3. 调用静态方法
// 注意:调用静态方法时,invoke 的第一个参数传 null
method.invoke(null, pi);
System.out.println("结果: " + pi);
System.out.println("---");
}
}
}
}
3.3 输出示例
原始列表: [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3]
调用方法: reverse()
[3, 9, 7, 9, 8, 5, 3, 5, 6, 2, 9, 5, 1, 4, 1, 3]
调用方法: sort()
[1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9]
调用方法: shuffle()
[5, 7, 4, 9, 9, 9, 2, 1, 6, 5, 3, 3, 1, 5, 3, 8]
✅ 说明:
- 找到了三个匹配方法:
reverse(),sort(),shuffle() - 静态方法的调用不依赖实例,
invoke(null, args…) - 这种方式可以用于动态处理集合或调用工具类方法
4. 总结
- Reflection 可以访问类的所有公共方法
- 可以动态调用实例方法和静态方法
-
异常处理:
-
ReflectiveOperationException统一处理反射异常
-
-
应用场景:
- 框架动态调用方法(如 ORM、注解处理)
- 工具类通用操作(如自动排序、集合操作)