[英]Scala interop with Java SAM without 2.12 M2 flag
是否有任何可接受的技術可以針對使用Java @FunctionalInterface / SAM / lambda表達式的Java-8 API編寫Scala代碼?
雖然Java lambda表達式互操作在M2 http://www.scala-lang.org/news/2.12.0-M2的標志下可用,但我更希望類型類/ AnyVal解決方案可以與scala一起使用.FunctionX特征。
不幸的是,scala.FunctionX擴展了AnyRef而不是Any,所以不能將這些特性用於/混合到隱式的AnyVal類實現中。
補充:即使scala.FunctionX是全局特征(從Any擴展),我也不確定我是如何實現目標的。 我的用例是這樣的:
在我的一個項目中,我選擇提供Java-8 API和FunctionalInterfaces,如Java Stream接口和類,以滿足最廣泛的基於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理解它們
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.