Scala 提供了 @varargs
注解,它会生成一个 Java 可变参数转发方法,使得我们可以像这样编写代码:
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");
我们在运行时遇到了这个异常:
java.lang.AbstractMethodError: Baz.bar([Ljava/lang/String;)V
我们可以确认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();
}
所以,不,转发器绝对不会被实现。
在两个bar
方法上放置注释会导致编译失败:
A method with a varargs annotation produces a forwarder method with the same
signature (args: Array[String])Unit as an existing method.
当然,仅在Baz
中的bar
上放置注解意味着我们无法使用来自Bar
实例的转发器。
这似乎像是个bug,但很容易遇到,并且我在问题跟踪器中没有看到任何信息。我的@varargs
使用正确吗?如果是,是否有一种解决方法可以让它执行你在这里期望的操作?