简体   繁体   English

Scala,IntelliJ:stackoverflow异常

[英]scala, IntelliJ: stackoverflow exception

lang.StackOverflow exception in my code, but I think the issue is with IntelliJ rather than the code issue. 我的代码中出现lang.StackOverflow异常,但我认为问题出在IntelliJ而不是代码问题。 So here is the deal (pieces of code): 所以这是交易(代码段):

case class Node(data: Int, children: ListBuffer[Node], parents: ListBuffer[Node])

val node1 = Node(thisGuy, ListBuffer[Node](), ListBuffer[Node]())
val node2 = Node(thatGuy, ListBuffer[Node](), ListBuffer[Node](node1))
node1.children.append(node2)

var nodes: mutable.Set[Node] = mutable.Set(node1)
// This is were I am getting stackoverflow exception
nodes.add(node2)

What am I missing here? 我在这里想念什么?

EDIT : I suspect this has something to do with toString method. 编辑 :我怀疑这与toString方法有关。 But I am not calling toString method on Node class. 但是我没有在Node类上调用toString方法。 Any chance that intellij is calling that method? intellij是否有可能调用该方法? If so, how to suppress it. 如果是这样,如何抑制它。

TIA TIA

When you add node2 as a child of node1 it creates a circular dependency. 当您将node2添加为node1的子代时,它将创建循环依赖项。 If you check what scala compiler generated for it: scalac -Xprint:typer NodeTest.scala 如果您检查为其生成了什么scala编译器: scalac -Xprint:typer NodeTest.scala

the hashCode function is like this: hashCode函数是这样的:

override <synthetic> def hashCode(): Int = {
  <synthetic> var acc: Int = -889275714;
  acc = Statics.this.mix(acc, data);
  acc = Statics.this.mix(acc, Statics.this.anyHash(children));
  acc = Statics.this.mix(acc, Statics.this.anyHash(parents));
  Statics.this.finalizeHash(acc, 3)
};

So for node1 to calculate hash code: it needs hash code of node2 (since node2 is a child of node1) and two calculate hash code of node2 it needs hash code of node1 (since node1 is parent of node2) 因此,要让node1计算哈希码:它需要node2的哈希码(因为node2是node1的子代),而两个计算node2的哈希码则需要node1的哈希码(因为node1是node2的父代)

Why hash code is important here? 为什么哈希码在这里很重要?

Because you are using Set which check if an element already exist before putting it in using hash code. 因为您正在使用Set,所以在使用哈希码将其放入之前检查元素是否已经存在。

BTW have you noticed that: 顺便说一句,您是否注意到:

node1.children.append(node2)
node1

Also gives stackoverflow. 还给出了stackoverflow。 I am not sure why but looks like toString also has issues with circular dependency. 我不确定为什么,但看起来toString也存在循环依赖问题。

EDIT: Case classes are generally meant for immutable data structures. 编辑:案例类通常用于不可变的数据结构。 So to model what you are trying to achieve you can use class. 因此,可以使用类来为要实现的目标建模。

class Node(val data: Int) {
   var parents : ListBuffer[Node] =  ListBuffer[Node]()
   var children : ListBuffer[Node] =  ListBuffer[Node]()
}
scala> val node1 = new Node(1)
node1: Node = Node@624ea235

scala> val node2 = new Node(2)
node2: Node = Node@12591ac8

scala> node1.children.append(node2)

scala> node2.parents.append(node1)

I suppose you have infinite recursion in equals or hashCode methods because of your class hierarchy. 我想由于类的层次结构,您在equalshashCode方法中具有无限递归。 Instances of Node have cyclic references to their parents and children so one of these methods runs infinitely. Node实例具有对其父代和子代的循环引用,因此这些方法之一可以无限运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM