【发布时间】:2010-05-03 03:29:24
【问题描述】:
Java 允许您创建一个全新的 Throwable 子类型,例如:
public class FlyingPig extends Throwable { ... }
现在,很少,我可能会这样做:
throw new FlyingPig("Oink!");
当然还有其他地方:
try { ... } catch (FlyingPig porky) { ... }
我的问题是:
- 这是个坏主意吗?如果是这样,为什么?
- 如果这是一个坏主意,可以采取什么措施来防止这种子类型化?
- 既然无法预防(据我所知),可能会导致什么灾难?
- 如果这不是一个坏主意,为什么不呢?
- 您如何利用
extends Throwable这一事实做出有用的事情?
- 您如何利用
提议的场景 #1
我真的想要做这样的事情的场景具有以下属性:
- “事件”是将最终发生的事情。这是预期的。它绝对不是
Error,也没有关于它何时发生的Exception-al。- 因为是意料之中的,所以会有
catch等着呢。它不会“溜走”任何东西。它不会“逃避”对catch通用Exception和/或Error的任何尝试。
- 因为是意料之中的,所以会有
- “事件”发生极少。
- 发生这种情况时,通常会有很深的堆栈跟踪。
所以也许现在我想说的很清楚了:FlyingPig 是穷举递归搜索的结果。
要搜索的对象存在:只要在搜索空间的大海中找到它。搜索过程将是一个漫长的过程,因此异常处理相对昂贵的成本可以忽略不计。事实上,使用boolean isFound 标志的传统控制流构造替代方案可能更昂贵,因为它必须在整个搜索过程中不断检查,很可能在递归的每个级别。此检查将在 99.99% 的情况下失败,但传播终止条件是绝对必要的。在某种程度上,虽然有效,但检查效率低下!
当找到寻找的对象时,只需throw-ing 一个FlyingPig,您就不必使用boolean isFound 标志的管理来弄乱代码。不仅在这方面代码更干净,而且由于这个遗漏,它可能运行得更快。
总而言之,选择是在这两者之间:
- 传统的控制流方法
- 使用
boolean isFound,不断检查 - 99.99% 的情况下,支票是“浪费”,因为它仍然是
false - 当它最终变为
true时,您将停止递归,并且您必须确保可以正确地展开到初始调用。
- 使用
-
FlyingPig方法- 不要打扰任何
boolean isFound。 - 如果找到,只需
throw new FlyingPig();这是预期的,所以会有一个catch。 - 不管理
boolean标志,不浪费检查是否需要继续,不记账手动展开递归等。
- 不要打扰任何
问题:
- 这种(ab)使用异常的技术是否有效? (有名字吗?)
- 如果有效,应该
FlyingPig extends Throwable还是Exception就可以了? (即使它的情况并没有什么特别之处?)
【问题讨论】:
-
有趣的想法,我只是在想这是否可以用来让JVM同步线程。捕获 throwable 是异步的吗?
-
我曾经使用过
class Finished extends Exception,原因完全相同:突破长递归搜索的性能。但我从来没有通过实际测量性能来证明这个原因。 -
@Christian:终于!和我有同样想法的人!我可能应该更进一步并进行基准测试。可能有一天会。
标签: java exception-handling throwable