专栏原创出处:github-源笔记文件 (opens new window) ,github-源码 (opens new window),欢迎 Star,转载请附上原文出处链接和本声明。
Java 核心知识专栏系列笔记,系统性学习可访问个人复盘笔记-技术博客 Java 核心知识 (opens new window)
# 一、使用 java.lang.reflect 包的 Method#invoke 调用
关键代码:Object invoke = method.invoke(null, Object... args)
,从底层方法被调用的对象设置为 null 即可。
public class ReflectExample {
public static String stringStaticMethod(String s) {
return s + "|" + s;
}
public static void main(String[] args) throws Throwable {
Method method = ReflectExample.class.
getDeclaredMethod("stringStaticMethod", String.class);
Object invoke = method.invoke(null, "invoke"); // obj 传 null
System.out.println(invoke); // invoke|invoke
}
}
java.lang.reflect.Method 类对应 invoke 方法说明:
在具有指定参数的方法对象上调用此方法对象表示的基础方法。 个别参数自动解包以匹配原始形式参数,原始参考参数和参考参数都需要进行方法调用转换。
如果底层方法是静态的,则指定的 obj 参数将被忽略。 它可能为 null。
如果底层方法所需的形式参数的数量为 0,则提供的 args 数组的长度为 0 或为空。
如果底层方法是一个实例方法,它将使用动态方法查找来调用,如“Java 语言规范”第二版,第 15.12.4.4 节所述; 特别是将会发生基于目标对象的运行时类型的覆盖。
如果底层方法是静态的,则如果尚未初始化该方法,那么声明该方法的类将被初始化。
如果方法正常完成,则返回的值将返回给调用者; 如果值具有原始类型,则首先将其适当地包装在对象中。 但是,如果该值具有基本类型的数组的类型,则该数组的元素不会包含在对象中; 换句话说,返回一个原始类型的数组。 如果底层方法返回类型为 void,则调用返回 null。
# 二、使用 java.lang.invoke 包的 MethodHandle 调用
JDK 7 为间接调用方法提供了 MethodHandle 类,即方法句柄。可以将其看作是反射的另一种方式。主要是为了虚拟机直接提供的动态语言支持。
public class InvokeExample {
public static String stringStaticMethod(String s) {
return s + "|" + s;
}
public static void main(String[] args) {
// 获取静态方法类型:返回值与参数均为 String
MethodType methodType = MethodType.methodType(String.class, String.class);
// 获取静态方法的句柄
MethodHandle method = MethodHandles.lookup()
.findStatic(InvokeExample.class, "stringStaticMethod", methodType);
// 调用方法
Object r = method.invoke("invoke"); // invoke|invoke
}
}
对 java.lang.invoke 包更深入的分析了解参考推荐专栏相关文章。