3

Is there a difference between a method parameter String* and Array[String]?

Console:

scala> def main(args: Array[String]): Unit = {}
main: (args: Array[String])Unit

scala> def main(args: String*): Unit = {}
main: (args: String*)Unit

Code 1:

object Example {
  def main(args: Array[String]): Unit = {
    println("Hello")
  }
}

>> Hello

Code 2:

object Example {
  def main(args: String*): Unit = {
    println("Hello")
  }
}

>> Exception in thread "main" java.lang.NoSuchMethodException: Example.main([Ljava.lang.String;)
    at java.lang.Class.getMethod(Class.java:1786)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:126)
1

2 Answers 2

7

Yes,

String* is a varargs, it takes in any number of Strings, which will be passed to the method as a Seq[String].

Array[String] take in a single Array of Strings.

If you have a sequence of String that you want to pass as a String*, you cannot do so directly, but you can "splat" out the sequence to pass it in using the :_* type ascription.

def varArg(input: String*){}

val strings = Seq("hello", "world")
varArg(strings:_*)
Sign up to request clarification or add additional context in comments.

4 Comments

So is String* a type or just how varargs is expressed in the console? How can I see in the console that it's passed to the method as Seq[String]? P.S. This old answer says it is passed as Array, did it change at some point to Seq? stackoverflow.com/a/1438796
@rapt I think it is a type but I'm not sure. It is only usable as a method parameter either way. The more upvoted and detailed answer form that question also mentions that it is a Seq. You can also find out for yourslef in the repel by defining a varargs method and seeing what you get. def test(args: String*) = args. We see that it returns a Seq[String], the actual implementation depends though, when we pass in arguments the concrete implementation is WrappedArray but if we pass no arguments it is Nil (the empty List aka. List())
I downvoted the linked answer for that error; Java uses arrays, Scala uses Seq. The repeated param has a type that is a Seq, scala-lang.org/files/archive/spec/2.12/…. The vararg itself is a type internal to the compiler, but we don't normally see that.
It would be cool if you could get the compiler to make a bridge to a varargs main, I don't know why they don't do that. Worth adding that this is what App is for.
2

I went and asked on the forum.

The annotation you want is annotation.varargs.

I had some inkling that they had that glue, but I never had a reason to use it.

Personally, I'd rather it were automatic for a main method, b/c obvious.

$ scala
Welcome to Scala 2.12.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_131).
Type in expressions for evaluation. Or try :help.

scala> object Main { @annotation.varargs def main(args: String*) =
     | println(args.size)
     | }
defined object Main

scala> Main.main(Array("hello","world"): _*)
2

OK, cool.

1 Comment

Probably my last input on SO.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.