Java 抽象方法和varargs注释
Scala提供了一种生成Java varargs转发器方法的方法,可以编写如下内容:Java 抽象方法和varargs注释,java,scala,variadic-functions,scala-java-interop,Java,Scala,Variadic Functions,Scala Java Interop,Scala提供了一种生成Java varargs转发器方法的方法,可以编写如下内容: import scala.annotation.varargs class Foo { @varargs def foo(args: String*): Unit = { args.foreach(println) } } 然后从Java调用此方法,而无需创建scala.Seq: Foo foo = new Foo(); foo.foo("a", "b"); 这很好 不幸的是,当方法是抽象
import scala.annotation.varargs
class Foo {
@varargs def foo(args: String*): Unit = {
args.foreach(println)
}
}
然后从Java调用此方法,而无需创建scala.Seq
:
Foo foo = new Foo();
foo.foo("a", "b");
这很好
不幸的是,当方法是抽象的时,转发部分似乎不会发生:
trait Bar {
@varargs def bar(args: String*): Unit
}
class Baz extends Bar {
def bar(args: String*): Unit = {
args.foreach(println)
}
}
现在,如果我们有以下Java代码:
Bar bar = new Baz();
bar.bar("a", "b");
我们(在运行时)得到此异常:
我们可以用javap
确认问题:
public interface Bar {
public abstract void bar(java.lang.String...);
public abstract void bar(scala.collection.Seq<java.lang.String>);
}
public class Baz implements Bar {
public void bar(scala.collection.Seq<java.lang.String>);
public Baz();
}
当然,只在Baz
中的bar
上添加注释意味着我们不能从bar
实例使用转发器
这似乎一定是个bug,但似乎也非常容易遇到,我在问题跟踪程序中没有看到任何东西。我是否正确使用
@varargs
?如果是这样的话,是否有一种变通方法可以让它实现您在这里期望的效果?我不知道Scala
,但在Java中,varargs只是一个数组
因此,在Java中,它将以这种方式工作,但有一个警告:
package tests.StackOverflow.q27052394;
import java.util.Arrays;
public class Runner {
public interface Bar {
public abstract void bar(java.lang.String ... ss);
}
public static class Baz implements Bar {
public void bar(java.lang.String[] array) {
System.out.println(Arrays.toString(array));
}
}
public static void main(String[] args) {
Bar b = new Baz();
b.bar("hello", "world");
}
}
如果你能用同样的方法愚弄Scala,你就会克服这个错误。实现你想要的一个方法是用Java定义接口,如下所示
interface Bar {
public void bar(String... args);
}
class Baz extends Bar {
def bar(args: String*): Unit = {
args.foreach(println)
}
}
然后在Scala中正常定义实现,如下所示
interface Bar {
public void bar(String... args);
}
class Baz extends Bar {
def bar(args: String*): Unit = {
args.foreach(println)
}
}
Scala编译器将认识到它需要生成vargs样式的方法,并将生成varargs和Seq实现
javap输出正如您所期望的那样
public class Baz implements Bar {
public void bar(scala.collection.Seq<java.lang.String>);
public void bar(java.lang.String[]);
public Baz();
}
interface Bar {
public abstract void bar(java.lang.String...);
}
公共类Baz实现Bar{
公共空白栏(scala.collection.Seq);
公共空栏(java.lang.String[]);
公共Baz();
}
接口条{
公共抽象空栏(java.lang.String…);
}
Oops。在我看来,这是另一个错误。多亏了彼此jugaad
互操作性解决方案。天哪!还有多少人躺在那里?看起来像只虫子。尝试向他们的问题跟踪器提交一个新的bug。将方法defbar(args:Array[String]):Unit=bar(args:*)
添加到Baz
实际上似乎很有效(尽管这不是很令人愉快)。