Как сериализовать лямбду Scala для взаимодействия с Java-методом?

У меня есть метод Java, который имеет параметр типа интерфейса SerializablePredicate.

@FunctionalInterface
interface SerializablePredicate<T> extends Predicate<T>, Serializable {}

Что мне нужно сделать, чтобы сериализовать лямбду Scala, такую ​​как

(x:String) => println(x)

так что он будет совместим с методом Java.

В настоящее время я пытаюсь разыграть лямбду

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)

2 ответа

Поскольку SerializablePredicate интерфейс SAM (единственный абстрактный метод), в Scala 2.12 вы можете просто написать

new SomeJavaClass(x => ...)

и лямбда будет скомпилирована в 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
}

и всякий раз, когда он находится в области видимости, вы можете передавать лямбду в методы / классы, которые принимают SerializablePredicate,

Обратите внимание, что в обоих случаях вы должны убедиться, что лямбда действительно сериализуема, то есть не захватывает никакие несериализуемые объекты.

Вы не можете разыграть Scala Function на Яву Functionalони не одно и то же. но вы можете попробовать сделать это так:

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

В приведенном выше коде: (t: T) => p.apply(t)Сотвори новый SerializablePredicate<T>JavaFunctionalInterface экземпляр для класса SomeJavaClass,

Есть пример для конвертации Scala Function на Яву Function:

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)
}

Так что в Скала, мы можем пройти Скала Function на Яву 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) 
Другие вопросы по тегам