为什么 Java 人经常默默地消费异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/921471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do Java people frequently consume exceptions silently?
提问by Sake
I never did any serious Java coding before, but I learned the syntax, libraries, and concepts based on my existing skills (Delphi & C#). One thing I hardly understand is that I've seen so much code that silently consume exceptions after printStackTracelike this:
我以前从未认真地编写过任何 Java 代码,但我根据我现有的技能(Delphi 和 C#)学习了语法、库和概念。我几乎不明白的一件事是,我已经看到了很多代码,在printStackTrace这样之后默默地消耗异常:
public void process() {
try {
System.out.println("test");
} catch(Exception e) {
e.printStackTrace();
}
}
There is similar code like this one in almost every Java article & project I ran into. Based on my knowledge this is very bad. The exception should almost always be forwarded to the outer context like this:
我遇到的几乎所有 Java 文章和项目中都有类似的代码。根据我的知识,这是非常糟糕的。异常应该几乎总是像这样转发到外部上下文:
public void process() {
try {
System.out.println("test");
} catch(Exception e) {
e.printStackTrace();
throw new AssertionError(e);
}
}
Most of the time the exception should end up being handled at the outermost loop which belongs to the underlying framework (Java Swing for example). Why does it look like the norm to code like this in the Java world? I'm puzzled.
大多数情况下,异常最终应该在属于底层框架(例如 Java Swing)的最外层循环中处理。为什么像这样的代码在 Java 世界中看起来很正常?我很困惑。
Based on my background, I'd prefer to remove printStackTrace entirely. I would simply rethrow as an unhandled aka RuntimeException(or, even better, AssertionError), then catch and log it at the most appropriate place: the framework outermost loop.
根据我的背景,我更愿意完全删除 printStackTrace 。我会简单地将其作为未处理的 aka RuntimeException(或者甚至更好AssertionError)重新抛出,然后在最合适的位置捕获并记录它:框架最外层循环。
public void process() {
try {
System.out.println("test");
} catch(Exception e) {
throw new AssertionError(e);
}
}
回答by OscarRyz
I have always thought, that's similar to the following scenario:
我一直认为,这类似于以下场景:
"A man gets shot.
He holds his breath and has enough strength to take a bus.
10 miles later the man gets off of the bus, walks a couple of blocks and dies."
“一个人被枪杀了。
他屏住呼吸,有足够的力气坐公交车。
10 英里后,这名男子下车,走了几个街区就死了。”
When the police gets to the body, they don't have a clue of what has just happened. They may have eventually but it is much harder.
当警察到达尸体时,他们对刚刚发生的事情一无所知。他们最终可能有,但要困难得多。
Better is:
更好的是:
"A man gets shot and he dies instantly, and the body lies exactly where the murder just happened."
“一个人被枪杀,当场死亡,尸体就在刚刚发生谋杀的地方。”
When the police arrives, all the evidence is in place.
当警察到达时,所有证据都已到位。
If a system is to fail, better is to fail fast
如果一个系统要失败,最好是快速失败
Addressing the question:
回答问题:
- Ignorance.
- +
- Sloth
- 无知。
- +
- 树懒
EDIT:
编辑:
Of course, the catch section is useful.
当然,catch 部分很有用。
If something can be done with the exception, that's where it should be done.
如果某些事情可以在例外情况下完成,那就应该在那里完成。
Probably that is NOT an exception for the given code, probably it is something that is expected ( and in my analogy is like a bulletproof Hymanet, and the man was waiting for the shot in first place ).
可能这不是给定代码的例外,可能是预期的东西(在我的比喻中就像一件防弹夹克,而那个人首先在等待射击)。
And yes, the catch could be used to Throw exceptions appropriate to the abstraction
是的,catch 可用于抛出适合抽象的异常
回答by Kris
Usually that is due to the IDE offering a helpful 'quick fix' that wraps the offending code in a try-catch block with that exception handling. The idea is that you actually DO something, but lazy developers don't.
通常这是由于 IDE 提供了一个有用的“快速修复”,将有问题的代码包装在带有异常处理的 try-catch 块中。这个想法是你实际上做了一些事情,但懒惰的开发人员没有。
This is bad form, no doubt.
毫无疑问,这是不好的形式。
回答by Bill the Lizard
This is a classic straw man argument. printStackTrace()is a debugging aid. If you saw it on a blog or in a magazine it was because the writer was more interested in illustrating a point otherthan exception handling. If you saw it in production code, the developer of that code was ignorant or lazy, nothing more. It shouldn't be held up as an example of common practice in the "java world".
这是一个经典的稻草人论调。 printStackTrace()是调试辅助工具。如果你看到它在博客或在一本杂志,这是因为笔者更感兴趣的是说明一点其他比异常处理。如果您在生产代码中看到它,那么该代码的开发人员就是无知或懒惰,仅此而已。它不应该被视为“java 世界”中常见做法的一个例子。
回答by AgileJon
- Java forces you to handle all Exceptions explicitly. If a method that your code calls is declared to throw FooException and BarException your code MUSThandle (or throw) those exceptions. The only exception to this is RuntimeException, which is silent like a ninja.
- Lots of programmers are lazy (myself included), and it's very easy to just print the stack trace.
- Java 强制您显式处理所有异常。如果您的代码调用的方法被声明为抛出 FooException 和 BarException,您的代码必须处理(或抛出)这些异常。唯一的例外是RuntimeException,它像忍者一样沉默。
- 许多程序员都很懒惰(包括我自己),打印堆栈跟踪非常容易。
回答by JaredPar
I find there are often 2 reasons this is done
我发现这样做通常有两个原因
- Programmer was lazy
- Programmer wanted to guard an entry point into there component (correctly or incorrectly)
- 程序员偷懒
- 程序员想要保护进入那里的组件的入口点(正确或错误)
I do not believe this is a phenomenon limited to Java. I've seen such coding often in C# and VB.Net as well.
我不相信这是仅限于 Java 的现象。我也经常在 C# 和 VB.Net 中看到这样的编码。
On the surface it's quite shocking and looks terrible. But really it's nothing new. It occurs all the time in C++ applications which use error code return values vs. exceptions. The difference though is that ignoring a potentially fatal return value doesn't really look any different than calling a function that returns void.
从表面上看,它非常令人震惊,看起来很可怕。但实际上这并不是什么新鲜事。它一直发生在使用错误代码返回值与异常的 C++ 应用程序中。但不同之处在于,忽略潜在的致命返回值与调用返回 void 的函数看起来并没有什么不同。
Foo* pFoo = ...;
pFoo->SomeMethod(); // Void or swallowing errors, who knows?
This code looks better but if SomeMethod() were to say return an HResult, it would be semantically no different than swallowing an exception.
这段代码看起来更好,但如果 SomeMethod() 说返回一个 HResult,它在语义上与吞下异常没有什么不同。
回答by dfa
because Checked Exceptionsis a failed experiment
因为Checked Exceptions是一个失败的实验
(maybe printStackTrace() is the real problem? :)
(也许 printStackTrace() 才是真正的问题?:)
回答by Rob
I have to say I slightly resent the tone that implies this sort of lax error-handling behaviour is something fundamental to Java programmers. Sure, Java programmers can be lazy, just like every other programmer, and Java's a popular language, so you'll probably see a lot of code swallowing exceptions.
我不得不说我有点反感这种暗示这种松懈的错误处理行为是 Java 程序员基本的东西的语气。当然,Java 程序员可能很懒惰,就像其他程序员一样,而且 Java 是一种流行的语言,因此您可能会看到很多代码吞下异常。
Also, as has been pointed out elsewhere, there are understandable frustrations with Java's enforced declaration of checked exceptions, although personally I don't have a problem with that.
此外,正如其他地方所指出的,Java 强制声明检查异常存在可以理解的挫折,尽管我个人对此没有问题。
What I have a problem with, I guess, is that you're breezing through a bunch of articles and code snippets on the web without bothering to consider the context. The truth is, when you're writing a technical article trying to explain how some particular API works, or how to get started with something, then you're very likely to skip over some aspects of the code - the error handling that's not directly related to what you're demonstrating is a likely candidate for disposal, especially if the exception is unlikely to occur in the example scenario.
我想我的问题在于,您正在浏览网络上的一堆文章和代码片段,而没有考虑上下文。事实是,当你写一篇技术文章试图解释某些特定 API 的工作原理,或者如何开始使用某些东西时,你很可能会跳过代码的某些方面 - 不是直接的错误处理与您正在演示的内容相关的是一个可能的处理候选对象,尤其是在示例场景中不太可能发生异常的情况下。
People who write articles of that nature have to maintain a reasonable signal-to-noise ratio, and rather fairly, I think, that means they have to assume you know some basics about the language you're developing in; how to deal properly with errors, and a bunch of other things. If you come across an article and notice a lack of proper error checking, then that's fine; just make sure that when you incorporate those ideas (but of course, never the exact code itself, right?) into your production code, you'll deal with all those bits and bobs that the author sensibly left out, in a manner that's most suited to what you're developing.
写这种性质的文章的人必须保持合理的信噪比,而且我认为相当公平,这意味着他们必须假设您了解您正在开发的语言的一些基础知识;如何正确处理错误以及其他一些事情。如果您遇到一篇文章并注意到缺乏适当的错误检查,那很好;只要确保当您将这些想法(当然,永远不会是确切的代码本身,对吗?)合并到您的生产代码中时,您将处理作者明智地遗漏的所有那些点点滴滴,以最有效的方式适合您正在开发的内容。
I do have a problem with very high-level introductory articles that breeze over such issues without ever returning to them, but please be aware that there's not some particular "mindset" of Java programmers regarding error handling; I know of plenty of your beloved C# programmers who don't bother dealing with all their problems, either.
我确实有一些非常高级的介绍性文章的问题,这些文章轻而易举地解决了这些问题而没有返回它们,但请注意,Java 程序员并没有一些关于错误处理的特定“心态”;我知道很多您心爱的 C# 程序员也不费心去处理他们的所有问题。
回答by Tim H
A System.out print or e.printStackTrace() - which implies use of System.out is usually a red flag meaning someone didn't bother to do a diligent job. Excepting desktop Java Applications, most Java apps are better off using logging.
System.out 打印或 e.printStackTrace() - 这意味着 System.out 的使用通常是一个危险信号,意味着有人没有费心去做勤奋的工作。除了桌面 Java 应用程序,大多数 Java 应用程序最好使用日志记录。
If the failure mode for a method is a no-operation, it's perfectly fine to eat an exception, whether you record the reason (and existence) or not. More typically, however, the catch clause should be taking some sort of exceptional action.
如果方法的失败模式是无操作,那么吃异常是完全可以的,无论您是否记录原因(和存在)。然而,更典型的是,catch 子句应该采取某种特殊的行动。
Rethrowing an exception is something that's best done when you either use the catch to clean up part of the work at a level where the necessary information is still available or when you need to transform the exception to an exception type more amenable to the caller.
重新抛出异常是最好的方法,当您使用 catch 清理部分工作时,必要信息仍然可用,或者当您需要将异常转换为更适合调用者的异常类型时。
回答by willcodejavaforfood
It is only consumed silently if the catch block is empty really.
如果 catch 块真的是空的,它只会被静默消耗。
As far as articles goes they are probably more interesting in proving some other point besides how to deal with exceptions. They just want to get straight to the point and have the shortest possible code.
就文章而言,除了如何处理异常之外,它们在证明其他一些观点方面可能更有趣。他们只是想直截了当并拥有尽可能短的代码。
Obviously you are right though, exceptions should at least be logged if they are going to be 'ignored'.
显然你是对的,如果异常将被“忽略”,至少应该记录它们。
回答by cwash
As others have pointed out, the reason you see this is for one of three reasons:
正如其他人所指出的,您看到这种情况的原因是以下三个原因之一:
- An IDE generated the try-catch block
- The code was copied and pasted
- The developer put the stacktrace in to debug but never came back to handle the exception properly
- IDE 生成了 try-catch 块
- 代码已复制粘贴
- 开发人员将堆栈跟踪放入调试中,但从未回来正确处理异常
The last point is the least likely to occur. I say this because I don't think anyone really debugs this way. Stepping through code with a debugger is a much easier way to debug.
最后一点最不可能发生。我这样说是因为我认为没有人真正以这种方式调试。使用调试器单步调试代码是一种更简单的调试方法。
The best description of what shouldbe done in a catch block can be found in Chapter 9 of Effective Javaby Joshua Bloch.
可以在Joshua Bloch的Effective Java的第 9 章中找到关于应该在 catch 块中做什么的最佳描述。

