[英]Java stack overflow because of recursive method call
我正在研究java中的學校作業,我遇到了一個錯誤,我無法找到答案。 不知何故,當我調用gethit()
方法通過返回的對象上iterator.next()
我得到堆棧溢出異常。 我懷疑因為gethit()
方法(在這種特定情況下)以遞歸方式調用自身。 盡管如此,我認為獲得堆棧溢出是很奇怪的,因為遞歸只有2或3級深度,並且我的對象不會使用過多的內存。
第一次調用gethit()
的shoot()
方法
public void shoot() {
assert canHaveAsEnergy(energy - 1000);
//Search the target position.
Position laserPos = new Position(getPos().getX(), getPos().getY(), getPos().getBoard());
do {
long nextX = laserPos.getX() + new Double(orientation.getDirection().getX()).longValue();
long nextY = laserPos.getY() + new Double(orientation.getDirection().getY()).longValue();
laserPos.setX(nextX);
laserPos.setY(nextY);
} while (getPos().getBoard().canHaveAsPosition(laserPos) && (! getPos().getBoard().hasAsPosition(laserPos)));
//Hit every entity on the target position.
for (Entity entity : getPos().getBoard().getAllEntitiesOn(laserPos)) {
entity.getHit();
}
setEnergy(energy - 1000);
}
getHit()
方法以遞歸方式調用自身。
public void getHit() {
ArrayList<Position> neighbours = new ArrayList<Position>();
Position northPos = new Position(getPos().getX(), getPos().getY() - 1, getPos().getBoard());
Position eastPos = new Position(getPos().getX() + 1, getPos().getY(), getPos().getBoard());
Position southPos = new Position(getPos().getX(), getPos().getY() + 1, getPos().getBoard());
Position westPos = new Position(getPos().getX() - 1, getPos().getY(), getPos().getBoard());
neighbours.add(northPos);
neighbours.add(eastPos);
neighbours.add(southPos);
neighbours.add(westPos);
for (Position pos : neighbours) {
if (getPos().getBoard().hasAsPosition(pos)) {
Iterator<Entity> iterator = getPos().getBoard().getAllEntitiesOn(pos).iterator();
while (iterator.hasNext()) {
//Somehow this gives a stack overflow error
iterator.next().getHit();
}
}
}
System.out.println(this.toString() + " takes a hit and explodes.");
getPos().getBoard().removeAsEntity(this);
terminate();
}
每次調用iterator時,都會調用另一個將調用另一個迭代器的迭代器,依此類推。 因此,由於每個迭代器調用,您的堆棧都會因無限遞歸而溢出
iterator.next().gethit();
每個迭代器只會創建一個需要經過的新迭代器,但是你會一次又一次地調用getHit(),所以你永遠不會完成任何函數調用。
iterator.next()getHit(); 調用getHit()方法並再次啟動迭代並繼續(遞歸循環)。 有一個變量或終止點來退出遞歸循環。
每當調用方法時,它都會將信息推送到堆棧幀,在方法完成時,堆棧幀將被刪除。 在您的情況下,無法完成方法並刪除堆棧幀,這會生成StackOverFlowError
在實現Recursion時,您應該確保有一個終止調用,其中方法不會調用自身。
現在你假設這個遞歸應該停止,因為你正在移動到鄰居並檢查它們是否被擊中但是當你看到呼叫時......(這是初始位置2,2的干運行)
[Original]=>[P1],[P2],[P3],[P4]
**[2,2]**=>[2,1],[3,2],[2,3],[1,2]
[2,1]=>[2,0],[3,1],**[2,2]**,[1,1]
[3,2]=>[3,1],[4,2],[3,3],[2,2]
[2,3]=>[2,2],[3,3],[2,4],[1,3]
[1,2]=>[1,1],[2,2],[1,3],[0,2]
所以這里當你首先計算4個鄰居並在其上調用getHit()
時。 Source單元格是任何一個鄰居的鄰居,這足以進入無休止的遞歸。
您可以通過輸入以下聲明來識別您的值...
public void getHit() {
System.out.println("[" + getPos().getX() + "," + getPos().getY() + "]");
....
}
這里的解決方案是保留一個單元格列表,將其作為參數傳遞,這些參數將被訪問,並且永遠不會再訪問它們。 希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.