将Scala单元转换为Java Void
我有一个Java类,它接受将Scala单元转换为Java Void,java,scala,type-conversion,typesafe,Java,Scala,Type Conversion,Typesafe,我有一个Java类,它接受函数[String,Void],类似于消费者函数接口。我从Scala代码中调用这个Java函数。正如您在下面看到的,我接受Scala端的函数:=>Unit,因为它是等效的。当我尝试应用此函数代替Void返回类型不匹配时。显式强制转换.asInstanceOf[Void]也引发了异常。如何将=>单元转换为=>无效 // Java class AcceptFunction { public void temp(Function<String, Void>
函数[String,Void]
,类似于消费者
函数接口。我从Scala代码中调用这个Java函数。正如您在下面看到的,我接受Scala端的函数:=>Unit
,因为它是等效的。当我尝试应用此函数代替Void
返回类型不匹配时。显式强制转换.asInstanceOf[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
})
}
//Java
类接受函数{
公共真空温度(功能f){
f、 申请(“你好”);
}
}
//斯卡拉
def温度(f:String=>单位):单位={
new AcceptFunction().temp(新函数[String,Void](){
覆盖def apply(t:String):Void=f(t)/您应该使用not函数
类型,因为您的函数
没有输出,并且消费者
用于此场景。例如:
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)
})
}
类接受函数{
public void temp(Consumer f){//无输出函数的Consumer
f、 接受(“你好”);
}
}
def温度(f:String=>单位):单位={
新的AcceptFunction().temp(新的使用者[字符串](){
覆盖def接受(t:字符串):单位=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.
scala>newjfunc.Acceptor().f(s=>println(s))
:12:错误:类型不匹配;
发现:单位
必填项:无效
新的jfunc.Acceptor().f(s=>println(s))
^
scala>new jfunc.Acceptor().f{s=>println(s);null}
你好,世界。
java与您展示的一样:
package jfunc;
import java.util.function.*;
public class Acceptor {
public void f(Function<String, Void> g) { g.apply("hello, world."); }
}
包jfunc;
导入java.util.function.*;
公共类接受者{
公共空间f(函数g){g.apply(“你好,世界”);}
}
它是:
scala> :javap -c -
public static final java.lang.Void $anonfun$res0$1(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
scala>:javap-c-
公共静态final java.lang.Void$anonfun$res0$1(java.lang.String);
代码:
0:getstatic#33//字段scala/Predef$.MODULE$:Lscala/Predef$;
3:aload_0
4:invokevirtual#37//方法scala/Predef$.println:(Ljava/lang/Object;)V
7:aconst_null
8:轮到你了
公共$line3.$read$$iw$$iw$();
代码:
0:aload_0
1:invokespecial#39//方法java/lang/Object。“:()V
4:aload_0
5:putstatic#41//字段模块$:L$line3/$read$$iw$$iw$;
8:aload_0
9:新的#43//jfunc类/接受器
12:dup
13:invokespecial#44//方法jfunc/Acceptor.“:()V
16:invokedynamic#63,0//invokedynamic#0:apply:()Ljava/util/function/function;
21:invokevirtual#67//方法jfunc/Acceptor.f:(Ljava/util/function/function;)V
24:getstatic#72//字段scala/runtime/BoxedUnit。单位:Lscala/runtime/BoxedUnit;
27:putfield#74//Field res0:Lscala/runtime/BoxedUnit;
30:返回
我有一个Java类,它接受函数[String,Void]
,类似于消费者
函数接口
那么这个类应该使用Consumer
。首先,近似地说,Function
从来都不是正确的类型。如果您不能更改它,至少要知道它是一个糟糕的设计,并且要小心使用这个库。Som snytt的回答已经说明了如何从Scala正确调用temp
,编写impl很简单如果需要,将icit从String=>Unit
转换为函数[String,Void]
。因此,下面的答案是关于其他尝试失败的原因
因为它是等效的
准确地说:它相当于void
,而不是void
。等效的Java代码将调用void
方法,例如消费者。接受:
public void tempOfVoid(Consumer<String> f) {
temp(new Function<String, Void> {
public Void apply(String x) {
return f.accept(x);
}
};
}
正如som snytt的答案在Scala中所示
现在,您可以问:Unit
是类型参数时会发生什么,因为void
不能是,或者当类型Unit
的值需要在运行时表示时(例如valx:Any=()
)?在这些情况下,Unit
由scala.runtime.BoxedUnit
类表示,正如Int
通常被转换为Int
,但有时转换为java.lang.Integer
。这解释了为什么强制转换为Void
会引发异常(并且不会导致编译错误).Void
不适合这些情况,因为它没有(非null
)值,而Unit
只有一个值:()
你的意思是。asInstanceOf[(String)=>Void]
?cf“我有一个Java类,它接受函数[String,Void],这类似于消费者函数接口。”那么这个类应该使用消费者
。如果您不能更改它,至少要知道它是一个糟糕的设计,并小心使用这个库。“因为它是等效的”是的,它相当于void
,而不是void
。因此,如果使用返回void
@AlexeyRomanov的Java方法,则会出现类型不匹配。我想了解互操作性,但我太懒了,我不需要它。我怀疑string=>单元应该很简单。也许你的答案应该是规范的?@som-snytt我已经把它扩展到了一个答案。谢谢你注意到这一点。我很好奇为什么上面的实现不起作用。
public Void apply(String x) {
f.accept(x);
return null;
}