How to use Scala varargs fields from Java (varargs annotation)

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is a short recipe, Recipe 17.5, “How to annotate varargs methods in Scala.”

Problem

You’ve created a Scala method with a varargs field, and would like to be able to call that method from Java code.

Solution

When a Scala method has a field that takes a variable number of arguments, mark it with the @varargs annotation.

For example, the printAll method in the following Scala class is marked with @varargs so it can be called as desired from Java:

package varargs

import scala.annotation.varargs

class Printer {
    @varargs def printAll(args: String*) {
        args.foreach(print)
        println
    }
}

The printAll method can now be called from a Java program with a variable number of parameters, as shown in this example:

package varargs;

public class Main {
    public static void main(String[] args) {
        Printer p = new Printer();
        p.printAll("Hello");
        p.printAll("Hello, ", "world");
    }
}

When this code is run, it results in the following output:

Hello
Hello, world

Discussion

If the @varargs annotation isn’t used on the printAll method, the Java code shown won’t even compile, failing with the following compiler errors:

Main.java:7: printAll(scala.collection.Seq<java.lang.String>) in
varargs.Printer cannot be applied to (java.lang.String)
[error]     p.printAll("Hello");
[error]      ^

Main.java:8: printAll(scala.collection.Seq<java.lang.String>) in
varargs.Printer cannot be applied to (java.lang.String,java.lang.String)
[error]     p.printAll("Hello, ", "world");
[error]      ^

Without the @varargs annotation, from a Java perspective, the printAll method appears to take a scala.collection.Seq<java.lang.String> as its argument.