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"); 这很好 不幸的是,当方法是抽象

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");
这很好

不幸的是,当方法是抽象的时,转发部分似乎不会发生:

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
实际上似乎很有效(尽管这不是很令人愉快)。