在Akka Streams中建议使用GraphStage
,但我找不到任何关于在Java中使用getStageActor()
方法的文档(我发现使用Scala的所有文档)。
如何将以下代码转换为Java?
lazy val self: StageActor = getStageActor(onMessage)
和
private def onMessage(x: (ActorRef, Any)): Unit =
{
x match {
case (_, msg: String) =>
log.info("received msg, queueing: {} ", msg)
messages = messages.enqueue(msg)
pump()
}
}
答案 0 :(得分:0)
之前我没有使用getStageActor()
,因此无法提供太多帮助。至于从Scala到Java的代码转换,如果需要允许,请打包一个包含Scala版本类的jar供Java app使用;否则,请考虑使用Java反编译器(例如cfr,procyon)来反编译Scala编译的类,并根据需要优化反编译的Java代码。
例如,反编译以下虚拟Scala代码将有助于揭示lazy val
和pattern matching
的骨架Java方式:
class Foo {
lazy val self = dummy(bar(_: String))
def dummy(u: Unit) = 1
private def bar(x: String): Unit = {
x match {
case "blah" => println(s"x = $x")
}
}
}
如下面的反编译代码所示,lazy val
在Java中完成,其值包含在synchronized
块内,并带有bitmap$0
布尔标志,pattern matching
转换为if
到MatchError
和$ java -jar /path/to/decompiler/cfr_0_125.jar Foo.class
private int self;
private volatile boolean bitmap$0;
private int self$lzycompute() {
Foo foo = this;
synchronized (foo) {
if (!this.bitmap$0) {
new Serializable(this){
public static final long serialVersionUID = 0L;
private final /* synthetic */ Foo $outer;
public final void apply(String x$1) {
this.$outer.Foo$$bar(x$1);
}
{
if ($outer == null) {
throw null;
}
this.$outer = $outer;
}
};
this.self = this.dummy(BoxedUnit.UNIT);
this.bitmap$0 = true;
}
return this.self;
}
}
public int self() {
return this.bitmap$0 ? this.self : this.self$lzycompute();
}
public int dummy(BoxedUnit u) {
return 1;
}
public void Foo$$bar(String x) {
String string = x;
if ("blah".equals(string)) {
Predef$.MODULE$.println((Object)new StringContext(
(Seq)Predef$.MODULE$.wrapRefArray((Object[])new String[]{"x = ", ""})
).s((Seq)Predef$.MODULE$.genericWrapArray((Object)new Object[]{x}))
);
BoxedUnit boxedUnit = BoxedUnit.UNIT;
return;
}
throw new MatchError((Object)string);
}
例外:
getNewsItems().then((result)=>{
if (result === "what you need") {
// do here what you want with the result data
} else {
buildNewsItemsViaHttp().then((result)=>{
if (result === "what you need") {
// do here what you want with the result data
} else {
buildNewsItemsViaLocalJSON.then((result)=>{
// do here what you need with result
})
}
})
}})
答案 1 :(得分:0)
根据getStageActor
method documentation,它接受类型
scala.Function1<scala.Tuple2<ActorRef,java.lang.Object>, scala.runtime.BoxedUnit>
在Scala中看起来像
((ActorRef, AnyRef)) => Unit
在Java中,此类型在语义上等效(使用Function
接口)
Function<Tuple<ActorRef, Object>, Void>
其中Tuple<A, B>
是一个包含两个A
和B
类型值的类。
因此,要调用getStageActor
方法,您需要创建上述类型的值。您可以通过构建扩展AbstractFunction1
的类的实例来直接执行此操作:
import scala.Function1;
import scala.Tuple2;
import scala.runtime.AbstractFunction1;
import scala.runtime.BoxedUnit;
getStateActor(new AbstractFunction1<Tuple2<ActorRef, Object>, BoxedUnit>() {
@Override
public BoxedUnit apply(Tuple2<ActorRef, Object> args) {
return BoxedUnit.UNIT;
}
});
如果你使用Java 8,那么使用lambda表达式有一些语法上更好的方法。
如果您使用Scala 2.12+,那么scala.Function1
是一个功能接口,您可以直接使用lambda表达式:
getStateActor((args: Tuple2<ActorRef, Object>) -> BoxedUnit.UNIT);
如果您使用旧版本的Scala,那么由于编译了特征的方式,Function1
不是功能接口,您需要使用scala-java8-compat库。有了它,代码看起来像
import static scala.compat.java8.JFunction.*;
getStateActor(func((args: Tuple2<ActorRef, Object>) -> BoxedUnit.UNIT));
然后,要实现该函数的逻辑,您可以使用_1()
和_2()
方法访问元组的元素:
(args: Tuple2<ActorRef, Object>) -> {
Object msg = args._2();
if (msg instanceof String) {
log.info("received msg, queueing: {} ", msg);
messages = messages.enqueue((String) msg);
pump();
}
return BoxedUnit.UNIT;
}
这是您想要转换的逻辑的直接翻译。