【问题标题】:How to serialize Scala lambda for interop with Java method?如何序列化 Scala lambda 以与 Java 方法互操作?
【发布时间】:2017-04-16 14:55:28
【问题描述】:

我有一个 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)

【问题讨论】:

    标签: java scala serialization scala-java-interop


    【解决方案1】:

    您不能将 Scala Function 转换为 Java Functional,它们不是一回事。但你可以尝试这样做:

    class SomeClass[T](val p:(T=>Boolean)) extends SomeJavaClass[T]((t: T) => p.apply(t)) {}
    

    在上面的代码中:(t: T) =&gt; p.apply(t),为SomeJavaClass类创建一个新的SerializablePredicate&lt;T&gt;JavaFunctionalInterfaceinstance

    有一个将 Scala Function 转换为 Java Function 的示例:

    Foo功能接口:

    @FunctionalInterface
    public interface Foo<T> { // Define a Java FunctionalInterface
        T apply(T t);
    }
    

    接受Foo函数作为参数的Bar类:

    public class Bar<T> {
        public Bar(Foo<T> foo)
    }
    

    所以在 Scala 中,我们可以通过以下方式将 Scala Function 传递给 Java class

    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) 
    

    【讨论】:

    • 我不确定你所说的“在上面的代码中是什么意思:(t: T) => p.apply(t), 为类创建一个新的 SerializablePredicate Java FunctionalInterface 实例SomeJavaClass”,你能举个例子吗?
    【解决方案2】:

    由于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 是实际上可序列化的,即不捕获任何不可序列化的对象。

    【讨论】:

    • 知道如何委托给返回 void 的 Java 方法吗?
    • void 的 Scala 等价物是 Unit,但它是一个真实类型。
    猜你喜欢
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多