对于使用Java @FunctionalInterface / SAM / lambda表达式的Java-8 API编写Scala代码是否有任何可接受的技术?
虽然Java http://www.scala-lang.org/news/2.12.0-M2中的标志下可以使用Java lambda表达式互操作,但我更希望类型类/ AnyVal解决方案可以与scala.FunctionX特征一起使用。
不幸的是,虽然scala.FunctionX扩展了AnyRef而不是Any,所以不能将这些特性用于/混合到隐式的AnyVal类实现中。
补充说:即使scala.FunctionX是全局特征(从Any扩展),我也不确定我是如何实现目标的。我的用例是这样的:
在我的一个项目中,我选择提供Java-8 API和FunctionalInterfaces,如Java Stream接口和放大器。类,以便迎合尽可能广泛的基于JVM的客户端语言的受众,例如关闭,斯卡拉,科特林。对于使用我的Java-8 API的每种客户端语言,如果访问Java-8 API时,我会编写适当的绑定(如果需要)以使用特定于语言的习惯用法。
顺便说一句。我也会对Kotlin-Java互操作环境中对此问题的任何评论感兴趣。
答案 0 :(得分:2)
这个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调用。)
贾斯汀约翰逊, 关于我的项目发条的微博, 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
*/
答案 1 :(得分:1)
顺便说一句。我也会对Kotlin-Java互操作环境中对此问题的任何评论感兴趣。
Kotlin的FunctionX
接口是SAM,所以没有必要做任何额外的事情来让Java 8理解它们