MethodHandle 能把小函数像积木一样拼成复杂的调用逻辑。每个组合器到底改了方法类型的哪一部分?写错类型会得到什么异常?拼出来的句柄慢不慢?这篇逐个运行,并量出 static final 与局部句柄的差别。
1 基础:add 的类型 (int,int)int;invokeExact(2,3) = 5
2 insertArguments(add, 0, 10):类型 (int)int;(5) = 15
3 dropArguments(add, 0, String):类型 (String,int,int)int;("忽略",2,3) = 5
4 filterArguments(add, 0, twice):先把第 1 个参数翻倍。类型 (int,int)int;(3,4) = 10(2*3+4=10)
5 filterReturnValue(len, twice):类型 (String)int;("abcd") = 8(4*2)
6 guardWithTest:类型 (int)String;(5) = 正数 5;(-2) = 非正数 -2
7 catchException(parse, NumberFormatException, fallback):("42") = 42;("abc") = -1
8a tryFinally 的清理句柄类型不匹配:IllegalArgumentException: target and return types must match: void != int
8 tryFinally(清理句柄必须返回与目标相同的类型):
[cleanup] t=null r=7
("7") = 7
[cleanup] t=NumberFormatException r=0
("zz") 抛出 NumberFormatException(cleanup 已先执行)
9 permuteArguments(greet, 交换两个参数):("小明","你好") = 你好, 小明!
10 foldArguments(sum3, 0, add):类型 (int,int)int;(1,2) = 6(先算 add(1,2) = 3 放到最前面,再 sum3(3, 1, 2) = 6)
11 collectArguments(add, 0, len):类型 (String,int)int;("abc",10) = 13(3+10)
12 asSpreader(int[], 2):类型 (int[])int;({4,5}) = 9
13 asVarargsCollector:isVarargsCollector=true;invoke(1,2,3) = [1, 2, 3];invoke() = []
14 countedLoop(0..4 累加):类型 ()int;() = 10(0+1+2+3+4)
15 asType 把 int 适配成 long/Integer/Object:3,3
16 invokeExact 类型不精确:WrongMethodTypeException: handle's method type (int,int)int but found (Object,Object)void
17 insertArguments 类型错误:ClassCastException: class java.lang.Integer is not compatible with class java.lang.String
18 identity/zero/empty/constant:原样,0,(String)void,固定值
19 组合句柄 (x) -> (1 + x) * 2 的调用耗时:直接 Java 方法 0.58 ns;static final 句柄 invokeExact 0.58 ns;非 static final 的局部句柄 invokeExact 2.26 ns;invoke(类型适配)4.61 ns(s=0)