2024 Clojure状态调查中分享您的想法!

欢迎!请参阅关于页面了解更多关于这个站点的工作原理的信息。

+1
编译器

在实现Cursive对新的功能接口转换支持的过程中,我发现Java如何看待这些和Clojure实现之间存在一些不一致性。我想检查这些是否是有意为之的。

  1. Clojure要求包含SAM(单个抽象方法)的类要有FunctionalInterface注解才能进行转换。然而Java没有这样的限制,JLS也没有提到这一点:[链接到JLS](https://docs.oracle.com/javase/specs/jls/se21/html/jls-9.html#jls-9.8)。这可能会产生问题,因为有可能存在库中的类没有这个注解,但是在Java中可以用括号使用,而在Clojure中则不行。对于旧版本的前lambda库中的类来说,这种情况可能很常见。似乎FunctionalInterface更多是为了确保一个打算作为SAM的接口保持为SAM,并且不会意外地添加到它(参见![链接](https://docs.oracle.com/javase/specs/jls/se21/html/jls-9.html#jls-9.6.4.9))。事实上,该部分明确指出,注解对于接口是功能性的不是必需的。
  2. 类似地,规范中说功能接口必须是一个接口,但是Compiler.FISupport.maybeFIMethod()没有检查这一点,它只检查该方法本身是否是抽象的。所以Clojure会接受包含SAM的抽象类,但Java不这样。这种情况似乎在实践中不太可能发生,但也很容易加强,我看不出不执行此操作的任何有用用例。

2 个答案

0
by
谢谢,我没看到这一点。很遗憾,这个问题不会在1.12中修复,这可能会让一些人陷入麻烦。

无论如何,我想我会实现编译器现在所做的事情。
0
by
编辑 by

1) 我们的目的是找出Clojure函数与Java构造之间有语义匹配的地方,并使它们在那里使用是隐式的。标记为这样的功能接口必须只有一个方法,并明确声明该意图。虽然SAM接口在结构上类似,但没有那种声明的意图,可能与Clojure函数的语义不匹配(而是“过程”或某种非功能性概念)。

话虽如此,SAM和方法值的组合是一个有趣的汇聚点,我们仍在努力研究。如果你将方法值传递给接受SAM的方法,那么我们可以在不创建方法值包装器并对其进行适配的情况下直接适配(正如Java使用方法引用那样)。这是一个没有Clojure函数也没有必要进行语义匹配的情况,我们可能还会支持这一点,尚待确定。

2) maybeFIMethod检查类是否有@FunctionalInterface注解,这个注解只能存在于接口上,因此没有必要检查它是否是一个接口。

...