如何声明scala方法,以便可以使用varargs样式从Java调用它

如何声明scala方法,以便可以使用varargs样式从Java调用它,java,scala,interop,variadic-functions,Java,Scala,Interop,Variadic Functions,我在scala库类中有两个简单的方法: class Foo { def bar(args : String*) : Unit = println("Foo.bar with: " + args) def bar(args : Array[String]) : Unit = bar(args.toSeq : _*) } 这些都编译得很好。然后我将其放入库foo.jar,并尝试编译以下Java片段: import Foo public class Test { public st

我在scala库类中有两个简单的方法:

class Foo {
  def bar(args : String*) : Unit = println("Foo.bar with: " + args)
  def bar(args : Array[String]) : Unit = bar(args.toSeq : _*)
}
这些都编译得很好。然后我将其放入库
foo.jar
,并尝试编译以下Java片段:

import Foo
public class Test {

    public static void main(String[] args) {
        Foo foo = new Foo();
        foo.bar("Hello", "World"); //DOES NOT COMPILE
    }
}
我可以用以下内容替换有问题的行:

foo.bar(new String[] { "Hello", "World" }); //OK

但这似乎违背了这一点。如何使用类似Java varargs的语法从Java调用它?

不完全确定,但我认为Scala中的varargs使用序列,与Java实现不同。我认为实现您想要的最简单的方法是在Java中对Foo scala类进行子类化,并添加一个采用Java vararg的bar方法,即

public class JavaFoo extends Foo {
    public void bar(String... args) {
         super.bar(args)
    }
}
然后可以使用Java中的vararg语法调用JavaFoo vararg方法

希望有帮助:)

在2.8(不知道2.7)中,如果您从Java父级重写varargs方法,或者从Java接口实现varargs方法,那么Scala编译器将生成两个方法,一个用于Scala,一个用于Java。Java one——正如您通过检查字节码所看到的那样——只需获取varargs数组并对其进行包装,然后将WrappedArray传递给需要Seq的Scala版本


如果有办法在其他情况下强制编译器生成转发器,我不知道。我怀疑它的存在。似乎提供一种请求它的方法(我猜是注释)将是一个合理的增强请求。

尽管有关于使用Java接口强制Scala编译器“兼容”的有用提示,我还是无法让代码正常工作。最终我意识到这些方法是在Scala对象上声明的,这意味着它们实际上是静态的,并且不能在接口中指定静态方法,因此编译器基本上忽略了对象实现接口的事实。幸运的是,我有一个工作机会。而不是像这样直接从Java调用静态方法:

CLASS.method(x,y,z)
CLASS$.MODULE$.method(x,y,z)
你必须这样称呼它:

CLASS.method(x,y,z)
CLASS$.MODULE$.method(x,y,z)
这意味着您实际上是以静态字段引用的实例的形式访问singleton对象,并且由于它是一个实例,并且实现了java接口,因此编译器在那里正确地完成了它的工作,并实现了varargs方法,以便java可以将其作为varargs调用

我个人认为这应该被视为Scala编译器的错误。

请参阅:

您可以使用
@annotation.varargs
指示scala生成这两种方法:

class Foo {
  @annotation.varargs def bar(args : String*) : Unit = println("Foo.bar with: " + args)
  def bar(args : Array[String]) : Unit = bar(args.toSeq : _*)
}

可能是打字错误,但class
Foo
没有
Foo
方法。我说的话显然是错的,尽管我承认这让我感到困惑。我删除我的答案是为了避免传播错误信息。嗯。。。尝试了Daniel的建议,但我无法使用scala 2.8 beta实现这一点。java vararg和scala vararg的编译是最近刚刚添加的吗?反编译字节码只会产生一个带有公共void bar(Seq args)方法的Foo类。。。