将 Scala 单位转换为 Java Void
Convert Scala Unit to Java Void
我有一个 Java class 需要 Function[String, Void]
,它类似于 Consumer
功能接口。我在 Scala 代码中调用这个 Java 函数。正如您在下面看到的,我在 Scala 方面接受 function: => Unit
,因为它等效于 void。当我尝试应用此函数代替 Void
return 类型时,会发生类型不匹配的情况。 .asInstanceOf[Void]
的显式转换也引发异常。我们如何将 => Unit
转换为 => Void
?
// Java
class AcceptFunction {
public void temp(Function<String, Void> f) {
f.apply("Hello");
}
}
// Scala
def temp(f: String => Unit): Unit = {
new AcceptFunction().temp(new Function[String, Void]() {
override def apply(t: String): Void = f(t) // <===== error expecting Void instead of Unit
})
}
您应该使用 Consumer 而不是 Function
类型,因为您的 Function
没有输出,而 Consumer
用于这种情况。喜欢:
class AcceptFunction {
public void temp(Consumer<String> f) { // Consumer for no output Function
f.accept("Hello");
}
}
def temp(f: String => Unit): Unit = {
new AcceptFunction().temp(new Consumer[String]() {
override def accept(t: String): Unit= f(t)
})
}
显然,
scala> new jfunc.Acceptor().f(s => println(s))
<console>:12: error: type mismatch;
found : Unit
required: Void
new jfunc.Acceptor().f(s => println(s))
^
scala> new jfunc.Acceptor().f { s => println(s) ; null }
hello, world.
其中 java 与您显示的一样:
package jfunc;
import java.util.function.*;
public class Acceptor {
public void f(Function<String, Void> g) { g.apply("hello, world."); }
}
确实如此:
scala> :javap -c -
public static final java.lang.Void $anonfun$res0(java.lang.String);
Code:
0: getstatic #33 // Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_0
4: invokevirtual #37 // Method scala/Predef$.println:(Ljava/lang/Object;)V
7: aconst_null
8: areturn
public $line3.$read$$iw$$iw$();
Code:
0: aload_0
1: invokespecial #39 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #41 // Field MODULE$:L$line3/$read$$iw$$iw$;
8: aload_0
9: new #43 // class jfunc/Acceptor
12: dup
13: invokespecial #44 // Method jfunc/Acceptor."<init>":()V
16: invokedynamic #63, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;
21: invokevirtual #67 // Method jfunc/Acceptor.f:(Ljava/util/function/Function;)V
24: getstatic #72 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
27: putfield #74 // Field res0:Lscala/runtime/BoxedUnit;
30: return
I have a Java class which takes Function[String, Void]
, which is similar to Consumer
functional interface.
那么这个class应该使用Consumer
。初步估计,Function<String, Void>
永远不是正确的类型。如果你不能改变它,至少要意识到它是一个糟糕的设计并小心使用这个库。 Som-snytt 的回答已经展示了如何从 Scala 中正确调用 temp
,如果需要,编写从 String => Unit
到 Function[String, Void]
的隐式转换也很简单。所以这个答案的其余部分是关于为什么你的其他尝试没有奏效的原因。
as it is void equivalent
准确地说:相当于void
,而不是Void
。等效的 Java 代码将调用 void
方法,例如Consumer.accept
:
public void tempOfVoid(Consumer<String> f) {
temp(new Function<String, Void> {
public Void apply(String x) {
return f.accept(x);
}
};
}
并且将无法进行类型检查。相反,你需要
public Void apply(String x) {
f.accept(x);
return null;
}
与 som-snytt 的回答在 Scala 中显示的相同。
现在,您可以问:当 Unit
是类型参数时会发生什么,因为 void
不能,或者当类型 Unit
的值需要表示时在运行时(一个例子是 val x: Any = ()
)?在这些情况下,Unit
由 scala.runtime.BoxedUnit
class 表示,就像 Int
通常被翻译成 int
但有时被翻译成 java.lang.Integer
一样。这解释了为什么强制转换为 Void
会引发异常(并且不会导致编译错误)。 Void
不是适合这些情况的翻译,因为它没有(非 null
)值,而 Unit
只有一个值:()
.
我有一个 Java class 需要 Function[String, Void]
,它类似于 Consumer
功能接口。我在 Scala 代码中调用这个 Java 函数。正如您在下面看到的,我在 Scala 方面接受 function: => Unit
,因为它等效于 void。当我尝试应用此函数代替 Void
return 类型时,会发生类型不匹配的情况。 .asInstanceOf[Void]
的显式转换也引发异常。我们如何将 => Unit
转换为 => Void
?
// Java
class AcceptFunction {
public void temp(Function<String, Void> f) {
f.apply("Hello");
}
}
// Scala
def temp(f: String => Unit): Unit = {
new AcceptFunction().temp(new Function[String, Void]() {
override def apply(t: String): Void = f(t) // <===== error expecting Void instead of Unit
})
}
您应该使用 Consumer 而不是 Function
类型,因为您的 Function
没有输出,而 Consumer
用于这种情况。喜欢:
class AcceptFunction {
public void temp(Consumer<String> f) { // Consumer for no output Function
f.accept("Hello");
}
}
def temp(f: String => Unit): Unit = {
new AcceptFunction().temp(new Consumer[String]() {
override def accept(t: String): Unit= f(t)
})
}
显然,
scala> new jfunc.Acceptor().f(s => println(s))
<console>:12: error: type mismatch;
found : Unit
required: Void
new jfunc.Acceptor().f(s => println(s))
^
scala> new jfunc.Acceptor().f { s => println(s) ; null }
hello, world.
其中 java 与您显示的一样:
package jfunc;
import java.util.function.*;
public class Acceptor {
public void f(Function<String, Void> g) { g.apply("hello, world."); }
}
确实如此:
scala> :javap -c -
public static final java.lang.Void $anonfun$res0(java.lang.String);
Code:
0: getstatic #33 // Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_0
4: invokevirtual #37 // Method scala/Predef$.println:(Ljava/lang/Object;)V
7: aconst_null
8: areturn
public $line3.$read$$iw$$iw$();
Code:
0: aload_0
1: invokespecial #39 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #41 // Field MODULE$:L$line3/$read$$iw$$iw$;
8: aload_0
9: new #43 // class jfunc/Acceptor
12: dup
13: invokespecial #44 // Method jfunc/Acceptor."<init>":()V
16: invokedynamic #63, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;
21: invokevirtual #67 // Method jfunc/Acceptor.f:(Ljava/util/function/Function;)V
24: getstatic #72 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
27: putfield #74 // Field res0:Lscala/runtime/BoxedUnit;
30: return
I have a Java class which takes
Function[String, Void]
, which is similar toConsumer
functional interface.
那么这个class应该使用Consumer
。初步估计,Function<String, Void>
永远不是正确的类型。如果你不能改变它,至少要意识到它是一个糟糕的设计并小心使用这个库。 Som-snytt 的回答已经展示了如何从 Scala 中正确调用 temp
,如果需要,编写从 String => Unit
到 Function[String, Void]
的隐式转换也很简单。所以这个答案的其余部分是关于为什么你的其他尝试没有奏效的原因。
as it is void equivalent
准确地说:相当于void
,而不是Void
。等效的 Java 代码将调用 void
方法,例如Consumer.accept
:
public void tempOfVoid(Consumer<String> f) {
temp(new Function<String, Void> {
public Void apply(String x) {
return f.accept(x);
}
};
}
并且将无法进行类型检查。相反,你需要
public Void apply(String x) {
f.accept(x);
return null;
}
与 som-snytt 的回答在 Scala 中显示的相同。
现在,您可以问:当 Unit
是类型参数时会发生什么,因为 void
不能,或者当类型 Unit
的值需要表示时在运行时(一个例子是 val x: Any = ()
)?在这些情况下,Unit
由 scala.runtime.BoxedUnit
class 表示,就像 Int
通常被翻译成 int
但有时被翻译成 java.lang.Integer
一样。这解释了为什么强制转换为 Void
会引发异常(并且不会导致编译错误)。 Void
不是适合这些情况的翻译,因为它没有(非 null
)值,而 Unit
只有一个值:()
.