3

我想适应String.startsWithfrom (String, String)booleanto (String[])boolean,以便它可以接受String[]参数,其中前两个参数将映射到(String, String). 因此,我写了下面的示例代码:

MethodHandle test =MethodHandles.publicLookup().findVirtual(String.class, "startsWith", MethodType.methodType(boolean.class, String.class));
String[] myArgs = {"result", "data", "sijie"};
MethodHandle adapt = test.asSpreader(String[].class, 2);
System.out.println("Adapt... "+ adapt.type().toString());
System.out.println("Compare Result: "+ adapt.invokeExact(myArgs)); //Expect to return false. 

MethodHandletoString.startsWith适应boolean (String[])于最初的适应。但结果表明adapt.invokeExact失败。

Adapt... (String[])boolean
Exception in thread "main" java.lang.invoke.WrongMethodTypeException: expected (String[])boolean but found (String[])Object
    at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:349)
    at java.lang.invoke.Invokers.checkExactType(Invokers.java:360)
    at org.bytecode.generation.sample.App.main(App.java:78)

堆栈跟踪中的新(String[])对象非常令人困惑。任何人都可以就如何解决它提供一些建议吗?

谢谢

这个问题可以抽象为:如何适应一个Methodhandle只接受的(String, String)boolean,以便它可以接受(String[])boolean参数?

4

2 回答 2

2

问题在于invokeExact调用 - 因为invokeExact是签名多态,您需要使用强制转换显式指定返回类型:

System.out.println("Compare Result: "+ (boolean)adapt.invokeExact(myArgs));

这就是堆栈跟踪试图告诉您的内容expected (String[])boolean but found (String[])Object- 因为您没有强制转换 to booleanjavac假设方法句柄将具有 type (String[])Object,但在运行时,它具有 type (String[])boolean。(顺序可能令人困惑。可以把它想象成“给定方法句柄,我希望在编译时记录什么类型invokeExact?”)

另请参阅我对Why can't I .invokeExact() here 的回答,即使 MethodType 没问题?. (该问题涉及子类型和所涉及的解决方案asType以及添加演员表,但信息相似。)

于 2015-01-31T02:09:54.003 回答
0

多次重试后得到解决方案。

MethodHandle guard =MethodHandles.publicLookup().findVirtual(String.class, "startsWith", MethodType.methodType(boolean.class, String.class));
String[] myArgs = {"result", "data", "sijie"};
guard.invokeWithArguments(Arrays.copyOfRange(myArgs, 0, guard.type().parameterCount()));
于 2015-01-31T01:53:41.113 回答