如何序列化 Scala lambda 以便与 Java 方法互操作?



我有一个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>JavaFunctionalInterface实例

有一个将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实际上是可序列化的,即不会捕获任何不可序列化的对象。

最新更新