2017-04-16 50 views
0

我有一个Java方法,它有一个接口类型SerializablePredicate的参数。如何序列化Scala lambda与Java方法进行互操作?

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

回答

1

你不能投斯卡拉FunctionJavaFunctional,它们是不一样的东西。但你可以尝试做它喜欢:

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

在上面的代码:(t: T) => p.apply(t),创造一个新的SerializablePredicate<T>JavaFunctionalInterface实例该类SomeJavaClass

有用于转换的示例斯卡拉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通过向的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) 
+0

我不确定你的意思是“在上面的代码中:(t:T)=> p.apply(t),为类SomeJavaClass创建一个新的SerializablePredicate Java FunctionalInterface实例”,你能提供一个请举例吗? – newlogic

1

由于SerializablePredicate是SAM(单一抽象方法)接口,在斯卡拉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是实际上是可序列化的,即不捕获任何不可序列化的对象。

+0

任何想法如何委派给返回无效的Java方法? – newlogic

+0

'void'的Scala等价物是'Unit',除了它是一个真正的类型。 –