我有一个Java方法,它的参数类型为SerializablePredicate。
@FunctionalInterface
interface SerializablePredicate<T> extends Predicate<T>, Serializable {}
我需要做什么才能序列化 Scala lambda,例如
(x:String) => println(x)
这样它就可以与 Java 方法兼容。
目前我正在尝试铸造 lambda
class SomeClass[T](val p:(T=>Boolean)) extends SomeJavaClass[T](p.asInstanceOf[SerializablePredicate[T]]) {}
这就是我得到的堆栈跟踪...
Exception in thread "main" java.lang.ClassCastException: Main$$anonfun$1 cannot be cast to io.cognitionbox.core.SerializablePredicate
at P.<init>(LogicJavaToScalaInterp.scala:11)
at Main$.delayedEndpoint$Main$1(Main.scala:9)
at Main$delayedInit$body.apply(Main.scala:3)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.App$$anonfun$main$1.apply(App.scala:76)
at scala.collection.immutable.List.foreach(List.scala:381)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
at scala.App$class.main(App.scala:76)
at Main$.main(Main.scala:3)
at Main.main(Main.scala)
你不能将ScalaFunction
转换为JavaFunctional
,它们不是一回事。 但你可以尝试这样做:
class SomeClass[T](val p:(T=>Boolean)) extends SomeJavaClass[T]((t: T) => p.apply(t)) {}
在上面的代码中:(t: T) => p.apply(t)
,为类SomeJavaClass
创建一个新的SerializablePredicate<T>
Java
FunctionalInterface
实例。
有一个将ScalaFunction
转换为JavaFunction
的示例:
Foo
功能界面:
@FunctionalInterface
public interface Foo<T> { // Define a Java FunctionalInterface
T apply(T t);
}
Bar
接受Foo
函数作为参数的类:
public class Bar<T> {
public Bar(Foo<T> foo)
}
因此,在 Scala 中,我们可以通过以下方式将ScalaFunction
传递给Javaclass
:
class B(c: String => String) extends A((t: String) => c.apply(t)) // convert c of Scala Function to Java Function
val s: String => String = s => s.toUpperCase
val b = new B(s)
由于SerializablePredicate
是一个SAM(单一抽象方法)接口,因此在Scala 2.12中您可以编写
new SomeJavaClass(x => ...)
并且 lambda 将被编译成一个SerializablePredicate
.如果需要支持较旧的 Scala 版本,可以创建隐式转换:
implicit def makeSerializable[A](p: A => Boolean): SerializablePredicate[A] = new SerializablePredicate[A] {
def test(x: A) = p(x) // or whatever Predicate's method is called
}
只要它在范围内,您就可以将 lambda 传递给需要SerializablePredicate
的方法/类。
请注意,在这两种情况下,您都必须确保 lambda实际上是可序列化的,即不会捕获任何不可序列化的对象。