评论者:ajoberstar
以下是我(链接:[这里是链接](https://github.com/ajoberstar/ike.cljj/blob/master/src/main/clojure/ike/cljj/function.clj) 文档:ike.cljj)库中的一个替代方法。这个方法使用 MethodHandles(即 java.lang.invoke 包)而不是常规反射。我不确定是否已经在抽象类上测试过这个方法。
用法看起来与 Ghadi 发布的类似
`
(defsam my-sam
java.util.function.Predicate
[x]
(= x "it matched"))
(-> (Stream/of "not a match" "it matched")
(.filter my-sam)
(.collect Collectors/toList)
(-> (IntStream/range 0 10)
(.filter (sam* java.util.function.IntPredicate odd?))
(.collect Collectors/toList)
`
它使用(链接:[这里是链接](https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandleProxies.html#asInterfaceInstance-java.lang.Class-java.lang.invoke.MethodHandle-))的 MethodHandleProxies.asInterfaceInstance 方法来创建一个代理实例,该实例调用一个调用 Clojure 函数的方法句柄。它不会尝试验证参数数量,它只是将 varargs 代理到 ISeq 的 applyTo。不确定这是否是最有效的方法,但对我来说很有效。
我认为(链接:[这里是链接](https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/invoke/MethodHandles.html))可能是满足此类用例的首选方法。不过,对我来说,要确切了解如何使用它有点困难,所以我并没有深入研究。
我对我的方法(以及 Ghadi 的方法)的主要功能性问题是,你必须明确提供你想要代理的接口。Java lambdas 和 Groovy Closures 可以用于期望 SAM 的方法,它只是根据方法期望的内容进行强制转换。理想情况下,Clojure 也应该支持这一点。
而不是不得不这样做
`
(-> (IntStream/range 0 10)
(.filter (sam* java.util.function.IntPredicate odd?))
(.collect Collectors/toList)
`
我想这样做
`
(-> (IntStream/range 0 10)
(.filter odd?)
(.collect Collectors/toList)
`