Как сериализовать лямбду 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>
Java
FunctionalInterface
экземпляр для класса 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)