2017-04-16 106 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',除了它是一個真正的類型。 –