与Java SAM没有2.12 M2标志的Scala互操作

有没有使用Java @FunctionalInterface / SAM / lambda表达式的Java-8 API编写Scala代码的公认技巧?

虽然Java lambda表达式inter-op在M2 http://www.scala-lang.org/news/2.12.0-M2中的一个标志下是可用的,但我更希望类/ AnyVal解决方案可能与scala一起工作功能X特点。

不幸的是,scala.FunctionX扩展AnyRef而不是Any,所以不能使用/混合这些特性到隐式的AnyVal类实现中。

补充:我不完全相信,即使scala.FunctionX是全球特征(从任何延伸)我如何实现我的目标。 我的用例是这样的:

在我的一个项目中,我选择了像Java Stream接口和类一样提供一个带有FunctionalInterfaces的Java-8 API,以便迎合尽可能广泛的基于JVM的客户端语言,例如Closure,Scala和Kotlin。 对于使用我的Java-8 API的每种客户端语言,如果在访问Java-8 API时,我将编写适当的绑定(如果需要的话)以使用特定于语言的习惯用法。

顺便说一句。 我也会对在Kotlin-Java互操作环境中提出的这个问题的任何评论感兴趣。

这个Scala程序演示了我的问题的一个方面,那就是如何让Scala函数伪装成Java 8 Lambdas。

在语法和惯用方面,通过创建一些隐式的Scala函数将Scala函数转换为它们的Java 8 FunctionalInterface对应类型,似乎可以正常工作。

当然,这个告诫是,这种方法没有利用Java 8通过invokedynamic来优化lambda创建的能力。

因此,这种方法导致为Scala函数实例创建JVM对象,这可能会影响与Java 8本机lambda相比的内存使用情况和性能。

对于硬币的另一面,也就是如何让Java 8 Lambdas伪装成Scala函数,我想我们必须编写一些Java代码来与Scala进行交互(如果一个人的目标是要有一个可调用的Scala API来自Java)。

Justin Johansson,关于我的项目发条的微博,JVM上的XPath / XQuery的新实现,作为Twitter上的@MartianOdyssey

https://twitter.com/MartianOdyssey

/** * Scala Functions masquerading as Java 8 Lambdas. * * (C) Justin Johansson 2015. * * Microblogging about my Project Clockwork, a * new implementation of XPath/XQuery on the JVM, * as @MartianOdyssey on Twitter (https://twitter.com/MartianOdyssey). * * Permission to use this code is granted under Apache License, * Version 2.0 and providing attribution is afforded to author, * Justin Johansson. */ package lab import scala.language.implicitConversions import java.util.{ Arrays => JArrays, List => JList } import java.util.function.{ Consumer => JConsumer, Function => JFunction, Predicate => JPredicate } import java.util.stream.{ Stream => JStream } object JLambda extends App { println("JLambda: Scala to Java 8 lambda test") implicit def func1ToJConsumer[T](func: T => Unit): JConsumer[T] = { new JConsumer[T] { def accept(arg: T): Unit = func(arg) } } implicit def func1ToJFunction[T, R](func: T => R): JFunction[T, R] = { new JFunction[T, R] { def apply(arg: T): R = func(arg) } } implicit def func1ToJPredicate[T](func: T => Boolean): JPredicate[T] = { new JPredicate[T] { def test(arg: T): Boolean = func(arg) } } val myList = JArrays.asList("cake", "banana", "apple", "coffee") println(s"myList = $myList") val myListFiltered: JStream[String] = myList.stream .filter { x: String => x.startsWith("c") } val myListFilteredAndMapped: JStream[String] = myListFiltered .map { x: String => x.toUpperCase } myListFilteredAndMapped.forEach { x: String => println(s"x=$x") } } /* Outputs: JLambda: Scala to Java 8 lambda test myList = [cake, banana, apple, coffee] x=CAKE x=COFFEE */ 

顺便说一句。 我也会对在Kotlin-Java互操作环境中提出的这个问题的任何评论感兴趣。

Kotlin的FunctionX接口是SAM的,所以没有必要做额外的事情来让Java 8了解它们