递归非常快(可能是因为它不需要在堆上分配任何东西)但可能会导致某些“罕见”输入上的堆栈溢出(在树的例子中,它将出现在任何不平衡的树上).显式版本较慢但不太可能导致堆栈溢出.
默认情况下使用递归实现是否安全,并通过执行显式实现从StackOverflowError异常中恢复?
这被认为是不好的做法吗?
这是一个代码的小例子:
interface Node { List<? extends Node> getSons(); } static int sizeRec (Node root) { int result = 1; for (Node son : root.getSons()) { result += sizeRec(son); } return result; } static int sizeStack (Node root) { Stack<Node> stack = new Stack<Node>(); stack.add(root); int size = 0; while (! stack.isEmpty()) { Node x = stack.pop(); size ++; for (Node son : x.getSons()) { stack.push(son); } } return size; } static int size (Node root) { try { return sizeRec(root); } catch (StackOverflowError e) { return sizeStack(root); } }
解决方法
除此之外,您不应该捕获“Erros”,它表示环境中的运行时问题.你应该问自己是否值得忘记一些好的做法.也许,你可以尝试调整运行时配置以适应应用程序或者放置额外的验证逻辑……你的呼叫在那里……但是考虑到安全性,你实际上不能说你很好,因为我们不知道堆栈状态如何现在,不同的JRE实现可能会有所不同..
最后,对于底部的问题:这是一种不好的做法,并不安全.
surely there are situations where a stack overflow might leave an application inconsistent just like a memory exhaustion. Just imagine that some object is constructed and then initialized with the help of nested internal method calls – if one of them throws,the object may very well be in a state not supposed to be possible,just as if an allocation had Failed. But that doesn’t mean that your solution couldn’t still be the best one
它有一个被称为错误而不是异常的理由……
来自docs:
public abstract class VirtualMachineError
extends Error:
Thrown to indicate that the Java Virtual Machine is broken or has run out of resources necessary for it to continue operatingpublic class Error extends Throwable: An Error is a subclass of Throwable that indicates serIoUs problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error,though a “normal” condition,is also a subclass of Error because most applications should not try to catch it. A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught,since these errors are abnormal conditions that should never occur. That is,Error and its subclasses are regarded as unchecked exceptions for the purposes of compile-time checking of exceptions.