这个隐式val如何导致StackOverFlowError?
object Complicit { // a class with name,default,and conversion function as implicit val case class CC[A](name: String,defaultValue: A)(implicit val convert: String => A) { def getFrom(s: String): A= try { convert(s) } catch { case t: Throwable => println("ERROR: %s".format(t)) // just to see the StackOverflowException defaultValue } } // this works fine object Works { val cc1= CC("first",0.1)(_.todouble) } // this causes java.lang.StackOverflowError due to the implicit object Fails { // !!! StackOverFlowError here implicit val stringTodouble: String => Double= { _.todouble } val cc2= CC("second",0.2) } def main(args: Array[String]) { // this works println("%s %f".format(Works.cc1.name,Works.cc1.getFrom("2.3"))) // this fails println("%s %f".format(Fails.cc2.name,Fails.cc2.getFrom("4.5"))) } }
我是否在做违法行为?
解决方法
我相信我可以回答这里发生的事情..它与其他隐式转换以及您刚创建的转换有关.如果你添加这个跟踪,你可以确认通常与哪些堆栈溢出有关 – 一个函数自己重复调用,直到java的堆栈空间崩溃:
implicit val stringsTodouble: String => Double= { x=>println("called inner "+x); x.todouble }
….
叫内在4.5
叫内在4.5
叫内在4.5
叫内在4.5
调用内部4.5ERROR:java.lang.StackOverflowError
我认为发生的事情是这样的 – todouble不是java字符串的自然功能,而是使用StringOps中的隐式转换(或StringLike,我不是很确定,但它是同一个问题).
因此,当您调用todouble时 – 编译器开始寻找可能包含函数“todouble”的隐式转换.理论上它可以是任何结果类.
但是 – 如果有几个隐式转换可以实现这一目标会发生什么?不幸的是,“Double”还包含功能todouble,如下所示:
val x = 44.4 x.todouble
你猜怎么着?这意味着你现在最接近范围的新隐式函数赢得了比赛,并且在圆圈中调用以完成“todouble” – 有效地尝试将字符串转换为double,以便重复调用todouble(在Double类上).我承认这很令人困惑,但证据确实合适.
这是修复..它符合解释并阻止递归调用.
implicit val stringsTodouble: String => Double= { java.lang.Double.parseDouble(_) }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。