Groovy3:如何获取“Java lambdas”而不是闭包?

问题描述 投票:0回答:1

我在 Groovy3 中做了一些测试,Java lambda 表达式大多被解释为闭包而不是功能接口实例。 如何使 lambda 以实用的方式(无强制)与泛型一起使用以及 Groovy4 相比如何?

@CompileStatic

// lambda (ok!)
Supplier<String> s = 5::toString
// decompiled
Supplier s = DefaultGroovyMethods::toString;

// closure (wth?)
Supplier<String> s
s = 5::toString
// decompiled
Supplier s = null;
Closure var3 = ScriptBytecodeAdapter.getMethodPointer(5, "toString"); 
s = (Supplier)ScriptBytecodeAdapter.castToType(var3, Supplier.class);

// lambda
void test(Supplier<String> s) {}
test(5::toString)
// decompiled
test(DefaultGroovyMethods::toString);

// fails with "Groovyc: The argument is a method reference, 
// but the parameter type is not a functional interface"
<T> void test(T s) {}
this.<Supplier<String>>test(5::toString)

// closure (fails without coercion)
List<Supplier<String>> list = [5::toString]

// lambda (works, but cumbersome)
Supplier<String> s = 5::toString
List<Supplier<String>> list = [s]

// closure (fails without coercion)
List<Supplier<String>> list = []
list.add(5::toString)

我希望静态编译的 Java lambda 语法始终强制执行 Java lambda 语义。

generics groovy lambda closures method-reference
1个回答
0
投票

Lambda 和方法引用是 Groovy 3 的新功能。考虑到这一点,静态编译 (

@CompileStatic
) 的目标是像 Java 一样工作。然而,有一些边缘情况作为错误出现并自 Groovy 3.0.0 以来已得到修复,而另一些则尚未修复。您已经遇到了其中一些边缘情况。

当 Groovy 无法检测到 lambda 或方法引用表达式的目标是函数式接口时,它会分别依靠闭包或方法指针处理。这就是为什么您会在拆分声明中看到“ScriptBytecodeAdapter.getMethodPointer”。

我有一个 bug 修复,该修复将进入 Groovy 3.0.22 中的 split 声明(请参阅 GROOVY-11363)。这种情况应该已经在 Groovy 4 中得到正确处理(正如您所期望的)。

请使用最新的 Groovy 5 alpha 版本(目前是我们的主分支)尝试上述每种情况,如果您发现任何内容无法按预期工作,请在此处开具新票证:https://issues .apache.org/jira/projects/GROOVY

© www.soinside.com 2019 - 2024. All rights reserved.