为什么使用RuntimeException
捕获catch(Throwable exc) {}
不被视为良好的编程习惯?处理RuntimeExceptions的正确方法是什么?
另外,为什么catch(Exception exc) {}
无法抓住RuntimeException
?这种行为是如何实现的?
答案 0 :(得分:17)
通常,RuntimeException
表示编程错误(在这种情况下,您无法“处理”它,因为如果您知道它可以避免错误)。
抓住任何这些一般例外(包括Throwable
)都是一个坏主意,因为这意味着你声称你了解每一个可能出错的情况,尽管如此,你仍然可以继续。有时候在堆栈的顶层捕获Exception
(但通常不是Throwable
)是合适的,例如在Web服务器中 - 因为通常在单个请求出现问题时,您通常希望保持服务器运行并响应进一步的请求。我通常不会捕获Throwable
,因为它包括Error
子类,这些子类通常用于表示真正的灾难性错误,通常最好通过终止进程来“处理”。
从根本上说,如果出现错误,你需要对继续执行某项任务非常谨慎 - 你需要对错误的含义有一个很好的了解,否则你可能会对错误的状态假设继续世界,让事情变得更糟。在大多数情况下(并非所有情况),简单地放弃请求比尝试继续进行更好,无论出现什么神秘故障。 (它确实非常依赖于上下文 - 例如,在尝试获取一条辅助信息时,您可能并不关心出了什么问题。)
至于捕捉Exception
没有抓住RuntimeException
- 这根本不是真的。 RuntimeException
唯一奇怪的是它(和子类)是未经检查的异常,而Exception
和Exception
的所有其他子类都被检查。
答案 1 :(得分:4)
归结为实际存在的不同类型的异常。
已检查的异常(即扩展Exception
的异常类)通常是从恢复的错误。
未经检查的异常(即显式扩展RuntimeException
的异常类)是指示预期行为或程序状态中的错误的异常。当你取消引用它时,如果对象的状态不是NullPointerException
,你就不会得到null
。
一揽子一切 - Exception
或Throwable
, 远 更糟糕 - 不是良好做法,因为您假设您可以从任何异常行为中恢复。在某些情况下,您不应该或实际上不能(例如OutOfMemoryError
catch(Throwable t)
)。此外,捕获运行时异常表示代码异味;这意味着你掩盖了编码错误。
明确关于你正在捕捉的内容。
除此之外:是的,catch Exception
也会抓住RuntimeException
,因为Exception
是RuntimeException
的超类。同样,Throwable
会抓住Exception
和Error
,这就是为什么写catch(Throwable t)
会更糟。
答案 2 :(得分:2)
Throwable是所有Exception
已检查和未选中(RuntimeException
)的超类和错误。
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.Error
理想情况下捕获错误不是一个好习惯。
当RuntimeException
延伸Exception
时,它会抓住所有RuntimeExcption
。