为什么使用varargs的重载方法导致StackOverflowError?

Nic*_*aro 1 scala variadic-functions

我实现了一个带有重载方法的Scala类,该方法可以带一个Iterable[String]或一个String*varargs参数:

class StackOverflow(names: Iterable[String]) {

  // This function creates a copy of the StackOverflow object
  // copy is needed but this cannot be a case class.
  private def copy(names: Iterable[String] = names) = new StackOverflow(names) // <- line 19

  // overloaded methods

  def withNames(names: Iterable[String]) = this.copy(names = names) // <- line 24

  def withNames(names: String*) = require(names.nonEmpty); withNames(names.toIterable) // <- line 26
}

object App {

  def main(args: Array[String]) = {
    val x1 = new StackOverflow(Seq("a", "b"))
    val x2 = x1.withNames("c", "d")
  }
}
Run Code Online (Sandbox Code Playgroud)

我希望x2能与名称的新对象cd,但价值x2,因为无限递归造成的StackOverflowError不能创建:

Exception in thread "main" java.lang.StackOverflowError
    at scala.collection.LinearSeqLike$class.thisCollection(LinearSeqLike.scala:48)
    at scala.collection.immutable.List.thisCollection(List.scala:84)
    at scala.collection.immutable.List.thisCollection(List.scala:84)
    at scala.collection.IterableLike$class.toIterable(IterableLike.scala:87)
    at scala.collection.AbstractIterable.toIterable(Iterable.scala:54)
    at test.StackOverflow.<init>(StackOverflow.scala:26)
    at test.StackOverflow.copy(StackOverflow.scala:19)
    at test.StackOverflow.withNames(StackOverflow.scala:24)
    at test.StackOverflow.<init>(StackOverflow.scala:26)
    at test.StackOverflow.copy(StackOverflow.scala:19)
    at test.StackOverflow.withNames(StackOverflow.scala:24)
    ...
Run Code Online (Sandbox Code Playgroud)

代码有什么问题?

Dav*_*ank 6

你被遗漏的牙箍困住了.

你甚至不需要这val x2 = x1.withNames("c", "d")条线.

def withNames(names: String*) = require(names.nonEmpty); withNames(names.toIterable)
Run Code Online (Sandbox Code Playgroud)

这实际上是:

def withNames(names: String*) = require(names.nonEmpty) // part of class
withNames(names.toIterable)  // part of constructor
Run Code Online (Sandbox Code Playgroud)

withNames(names.toIterable)绝对正确,因为names你的班级也是一个领域.

因此,无论何时实例化StackOverflow对象,构造函数都会调用withNames()它来创建一个新实例,即调用withNames()等等.要解决此问题,您必须在方法定义周围使用大括号.当然,既然你正在重载withNames(),你也必须指定返回类型.