Java 使用 try/catch 防止应用程序崩溃
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42942952/
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
Using try/catch for preventing app from crashes
提问by mallaudin
I have been working on an Android app which uses try/catch
frequently to prevent it from crashing even on places where there is no need. For example,
我一直在开发一个 Android 应用程序,它try/catch
经常使用以防止它在不需要的地方崩溃。例如,
A view in xml layout
with id = toolbar
is referenced like:
xml layout
with 中的视图id = toolbar
引用如下:
// see new example below, this one is just confusing
// it seems like I am asking about empty try/catch
try {
View view = findViewById(R.id.toolbar);
}
catch(Exception e) {
}
This approach is used throughout the app. The stack trace is not printed and it's really hard to find what went wrong. The app closes suddenly without printing any stack trace.
这种方法在整个应用程序中使用。堆栈跟踪没有打印出来,很难找到哪里出了问题。该应用程序突然关闭而不打印任何堆栈跟踪。
I asked my senior to explain it to me and he said,
我让我的前辈向我解释,他说,
This is for preventing crashing in production.
这是为了防止在生产中崩溃。
I totally disagree with it. To me this is not the way to prevent apps from crashes. It shows that developer doesn'tknow what he/she is doing and is in doubt.
我完全不同意。对我来说,这不是防止应用程序崩溃的方法。它表明开发人员不知道他/她在做什么并且有疑问。
Is this the approach being used in industry to prevent enterprise apps from crashes?
这是行业中用于防止企业应用程序崩溃的方法吗?
If try/catch
is really, really our need then is it possible to attach an exception handler with UI thread or other threads and catch everything there? That will be a better approach if possible.
如果try/catch
真的,真的是我们的需要,那么是否可以使用 UI 线程或其他线程附加异常处理程序并捕获那里的所有内容?如果可能,这将是一个更好的方法。
Yes, empty try/catch
is bad and even if we print stack trace or log exception to server, wrapping blocks of code in try/catch
randomly across all the app doesn't make sense to me e.g. when every function is enclosed in a try/catch
.
是的,空try/catch
是不好的,即使我们向服务器打印堆栈跟踪或记录异常,try/catch
在所有应用程序中随机包装代码块对我来说也没有意义,例如当每个函数都包含在try/catch
.
UPDATE
更新
As this question has got a lot of attention and some people have misinterpreted the question (perhaps because I haven't phrased it clearly) I am going to rephrase it.
由于这个问题引起了很多关注,有些人误解了这个问题(可能是因为我没有明确表达),我将重新表述它。
Here is what developers are doing here
这是开发人员在这里做的事情
A function is written and tested, it can be a small function which just initializes views or a complex one, after testing it is wrapped around
try/catch
block. Even for function which will never throw any exception.This practice is used throughout the application. Sometime stack trace is printed and sometime just a
debug log
with some random error message. This error message differ from developer to developer.With this approach, app does not crash but behavior of the app becomes undetermined. Even sometime it is hard to follow what went wrong.
The real question I have been asking was; Is it the practice being following in the industry for preventing the enterprise applications from crashes?and I am not asking about empty try/catch. Is it like, users love application which do not crash than applications which behave unexpectedly? Because it really boils down to either crash it or present the user with a blank screen or the behaviour user is unaware of.
I am posting a few snippets from the real code here
private void makeRequestForForgetPassword() { try { HashMap<String, Object> params = new HashMap<>(); String email= CurrentUserData.msisdn; params.put("email", "blabla"); params.put("new_password", password); NetworkProcess networkProcessForgetStep = new NetworkProcess( serviceCallListenerForgotPasswordStep, ForgotPassword.this); networkProcessForgetStep.serviceProcessing(params, Constants.API_FORGOT_PASSWORD); } catch (Exception e) { e.printStackTrace(); } } private void languagePopUpDialog(View view) { try { PopupWindow popupwindow_obj = popupDisplay(); popupwindow_obj.showAsDropDown(view, -50, 0); } catch (Exception e) { e.printStackTrace(); } } void reloadActivity() { try { onCreateProcess(); } catch (Exception e) { } }
一个函数被编写和测试,它可以是一个只初始化视图的小函数,也可以是一个复杂的函数,在测试后它被包裹在
try/catch
块中。即使对于永远不会抛出任何异常的函数。这种做法贯穿整个应用程序。有时会打印堆栈跟踪,有时会打印
debug log
一些随机错误消息。此错误消息因开发人员而异。使用这种方法,应用程序不会崩溃,但应用程序的行为变得不确定。即使有时也很难跟踪哪里出了问题。
我一直在问的真正问题是;是不是业界正在遵循的防止企业应用程序崩溃的做法?我不是在问空的 try/catch。是不是用户喜欢不会崩溃的应用程序而不是行为异常的应用程序?因为它实际上归结为要么崩溃,要么向用户展示空白屏幕或用户不知道的行为。
我在这里发布了一些真实代码的片段
private void makeRequestForForgetPassword() { try { HashMap<String, Object> params = new HashMap<>(); String email= CurrentUserData.msisdn; params.put("email", "blabla"); params.put("new_password", password); NetworkProcess networkProcessForgetStep = new NetworkProcess( serviceCallListenerForgotPasswordStep, ForgotPassword.this); networkProcessForgetStep.serviceProcessing(params, Constants.API_FORGOT_PASSWORD); } catch (Exception e) { e.printStackTrace(); } } private void languagePopUpDialog(View view) { try { PopupWindow popupwindow_obj = popupDisplay(); popupwindow_obj.showAsDropDown(view, -50, 0); } catch (Exception e) { e.printStackTrace(); } } void reloadActivity() { try { onCreateProcess(); } catch (Exception e) { } }
It is notduplicate of Android exception handling best practices, there OP is trying to catch exception for a differentpurpose than this question.
它不是Android 异常处理最佳实践的副本,OP 正试图为 与此问题不同的目的捕获异常。
采纳答案by GhostCat
Of course, there are always exceptions to rules, but if you need a rule of thumb - then you are correct; empty catch blocks are "absolutely" bad practice.
当然,规则总是有例外的,但如果你需要一个经验法则——那么你是对的;空的 catch 块“绝对”是不好的做法。
Let's have a closer look, first starting with your specific example:
让我们仔细看看,首先从你的具体例子开始:
try {
View view = findViewById(R.id.toolbar);
}
catch(Exception e) { }
So, a reference to something is created; and when that fails ... it doesn't matter; because that reference isn't used in the first place! The above code is absolutely useless line noise. Or does the person who wrote that code initially assume that a second, similar call would magically no longer throw an exception?!
因此,创建了对某物的引用;当失败时……没关系;因为一开始就没有使用该引用!上面的代码是绝对没用的线路噪声。或者编写该代码的人最初是否假设第二个类似的调用将神奇地不再抛出异常?!
Maybe this was meant to look like:
也许这是为了看起来像:
try {
View view = findViewById(R.id.toolbar);
... and now do something with that view variable ...
}
catch(Exception e) { }
But again, what does this help?! Exceptions exist to communicaterespectively propagateerror situations within your code. Ignoring errors is rarely a good idea. Actually, an exception can be treated in ways like:
但是,这又有什么帮助呢?!也有例外,以传达分别繁殖自己的代码中的错误情况。忽略错误很少是一个好主意。实际上,可以通过以下方式处理异常:
- You give feedback to the user; (like: "the value you entered is not a string, try again"); or to engage in more complex error handling
- Maybe the problem is somehow expected and can be mitigated (for example by giving a "default" answer when some "remote search" failed)
- ...
- 您向用户提供反馈;(例如:“您输入的值不是字符串,请再试一次”);或者进行更复杂的错误处理
- 也许这个问题在某种程度上是可以预料的并且可以减轻(例如,当某些“远程搜索”失败时给出“默认”答案)
- ...
Long story short: the minimumthing that you do with an exception is to log/trace it; so that when you come in later debugging some problem you understand "OK, at this point in time that exception happened".
长话短说:您对异常所做的最少事情就是记录/跟踪它;这样当您稍后调试某个问题时,您就会明白“好的,此时发生了异常”。
And as others have pointed out: you also avoid catching for Exceptionin general (well, depending on the layer: there might be good reasons to have some catch for Exception, and even some kinds of Errors at the highest level, to make sure that nothinggets lost; ever).
正如其他人指出的那样:您通常也避免捕获Exception(好吧,取决于层:可能有充分的理由捕获Exception,甚至是最高级别的某些类型的错误,以确保没有任何东西会丢失;永远)。
Finally, let's quoteWard Cunningham:
最后,让我们引用Ward Cunningham 的话:
You know you are working with clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem.
当您阅读的每个例程都与您预期的差不多时,您就知道您正在使用干净的代码。当代码也使它看起来像是为问题而设计的语言时,您可以称其为漂亮的代码。
Let that sink in and meditate about it. Clean code does notsurprise you. The example you are showing to us surprises everybodylooking at.
让它沉浸并冥想它。干净的代码并不会令你大吃一惊。你向我们展示的例子让每个人都感到惊讶。
Update, regarding the update that the OP asks about
更新,关于 OP 询问的更新
try {
do something
}
catch(Exception e) {
print stacktrace
}
Same answer: doing that "all over the place" is also badpractice. Because this code is alsosurprising the reader.
相同的答案:“到处”这样做也是不好的做法。因为这段代码也让读者感到惊讶。
The above:
以上:
- Prints error information somewhere. It is not at allguaranteed that this "somewhere" resembles a reasonabledestination. To the contrary. Example: within the application I am working with, such calls would magically appear in our trace buffers. Depending on context, our application might pump tons and tons of data into those buffers sometimes; making those buffer prune every few seconds. So "just printing errors" often translates to: "simply loosing all such error information".
- Then: you don't do try/catch because you can. You do it because you understand what your code is doing; and you know: I better have a try/catch here to do the right thing (see the first parts of my answer again).
- 在某处打印错误信息。完全不能保证这个“某处”类似于一个合理的目的地。与此相反的。示例:在我正在使用的应用程序中,此类调用会神奇地出现在我们的跟踪缓冲区中。根据上下文,我们的应用程序有时可能会将大量数据注入这些缓冲区;每隔几秒钟就修剪一次这些缓冲区。所以“只是打印错误”通常翻译为:“只是丢失所有这些错误信息”。
- 然后:你不做 try/catch 因为你可以。你这样做是因为你了解你的代码在做什么;而且您知道:我最好在这里尝试/捕获以做正确的事情(再次参见我的答案的第一部分)。
So, using try/catch as "pattern" like you are showing; is as said: still not a good idea. And yes, it preventscrashes; but leads to all kind of "undefined" behavior. You know, when you just catch an exception instead of properlydealing with it; you open a can of worms; because you might run into myriads of follow-onerrors that you later don't understand. Because you consumed the "root cause" event earlier on; printed it somewhere; and that somewhereis now gone.
所以,像你展示的那样使用 try/catch 作为“模式”;就是说:仍然不是一个好主意。是的,它可以防止崩溃;但会导致各种“未定义”行为。您知道,当您只是捕获异常而不是正确处理它时;你打开一罐蠕虫;因为您可能会遇到无数后来不了解的后续错误。因为您之前消耗了“根本原因”事件;在某处打印出来;而那个地方现在已经消失了。
回答by Raman Sahasi
It's definitely a bad programming practice.
这绝对是一种糟糕的编程习惯。
From the current scenario, if there are hundreds of try
catch
like this, then you won't even know where the exception occurs without debugging the application, which is a nightmare if your application is in production environment.
从目前的场景来看,如果有数百个try
catch
这样的,那么不调试应用程序甚至不知道异常发生在哪里,如果您的应用程序在生产环境中,这将是一场噩梦。
But you can include a logger so that you get to know when an exception is throws (and why). It won't change your normal workflow.
但是您可以包含一个记录器,以便您了解何时抛出异常(以及为什么)。它不会改变您的正常工作流程。
...
try {
View view = findViewById(R.id.toolbar);
}catch(Exception e){
logger.log(Level.SEVERE, "an exception was thrown", e);
}
...
回答by shijin
I have been developing android apps for the past 4-5 years and never used a try catch for view initialisation.
在过去的 4-5 年里,我一直在开发 android 应用程序,但从未使用过 try catch 进行视图初始化。
If its a toolbar do like this
如果它的工具栏这样做
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
eg:- To get a TextView from a view(fragment/dialog/any custom view)
例如:- 从视图中获取 TextView(片段/对话框/任何自定义视图)
TextView textview = (TextView) view.findViewById(R.id.viewId);
TextView textview = (TextView) view.findViewById(R.id.viewId);
TextView textview = (TextView) view.findViewById(R.id.viewId);
instead of this
而不是这个
View view = findViewById(R.id.toolbar);
A view object has minimum reach compared to its real view type.
视图对象与其真实视图类型相比具有最小范围。
Note:- May be it crashed because the view was loaded. But adding try catch is a bad practice.
注意:- 可能是因为视图已加载而崩溃。但是添加 try catch 是一种不好的做法。
回答by Chandrani Chatterjee
Yes, try/catch is used to prevent app from crashing but You certainly don't need try/catch for fetching a view from XML as depicted in your question.
是的,try/catch 用于防止应用程序崩溃,但您当然不需要 try/catch 来从问题中描述的 XML 获取视图。
try/catch is generally used while making any http request, while parsing any String to URL, creating URL connections, etc. and also make sure to print stack trace. Not printing it doesn't make much sense in surrounding it with try/catch.
try/catch 通常用于发出任何 http 请求、将任何字符串解析为 URL、创建 URL 连接等,并确保打印堆栈跟踪。不打印它在用 try/catch 包围它时没有多大意义。
回答by Paresh P.
From the Android documentation:
Let's entitle it as -
让我们把它命名为——
Don't Catch Generic Exception
It can also be tempting to be lazy when catching exceptions and do something like this:
try { someComplicatedIOFunction(); // may throw IOException someComplicatedParsingFunction(); // may throw ParsingException someComplicatedSecurityFunction(); // may throw SecurityException // phew, made it all the way } catch (Exception e) { // I'll just catch all exceptions handleError(); // with one generic handler! }
In almost all cases it is inappropriate to catch generic
Exception
or Throwable (preferably not Throwable because it includes Error exceptions). It is very dangerous because it means that Exceptions you never expected (includingRuntimeExceptions
likeClassCastException
) get caught in application-level error handling.It obscures the failure handling properties of your code, meaning if someone adds a new type of
Exception
in the code you're calling, the compiler won't help you realize you need to handle the error differently.
不要捕获通用异常
在捕获异常并执行以下操作时也可能很懒惰:
try { someComplicatedIOFunction(); // may throw IOException someComplicatedParsingFunction(); // may throw ParsingException someComplicatedSecurityFunction(); // may throw SecurityException // phew, made it all the way } catch (Exception e) { // I'll just catch all exceptions handleError(); // with one generic handler! }
在几乎所有情况下,捕获泛型
Exception
或 Throwable都是不合适的(最好不是 Throwable,因为它包含错误异常)。这是非常危险的,因为这意味着您从未预料到的异常(包括RuntimeExceptions
likeClassCastException
)会在应用程序级错误处理中被捕获。它掩盖了您代码的故障处理属性,这意味着如果有人
Exception
在您调用的代码中添加了一种新类型,编译器将无法帮助您意识到您需要以不同方式处理错误。
Alternatives to catching generic Exception:
- Catch each exception separately as separate catch blocks after a single try. This can be awkward but is still preferable to catching all Exceptions.
Edit by author: This one is my choice.Beware repeating too much code in the catch blocks. If you are using Java 7 or above, use multi-catch to avoid repeating the same catch block.- Refactor your code to have more fine-grained error handling, with multiple try blocks. Split up the IO from the parsing, handle errors separately in each case.
- Re-throw the exception. Many times you don't need to catch the exception at this level anyway, just let the method throw it.
捕获通用异常的替代方法:
- 一次尝试后,将每个异常作为单独的 catch 块单独捕获。这可能很尴尬,但仍然比捕获所有异常更可取。
作者编辑:这是我的选择。当心在 catch 块中重复过多的代码。如果您使用的是 Java 7 或更高版本,请使用 multi-catch 以避免重复相同的 catch 块。- 重构您的代码以使用多个 try 块进行更细粒度的错误处理。从解析中拆分 IO,在每种情况下分别处理错误。
- 重新抛出异常。很多时候你无论如何都不需要在这个级别捕获异常,只需让方法抛出它即可。
In most cases you shouldn't be handling different types of exception the same way.
在大多数情况下,您不应该以相同的方式处理不同类型的异常。
Formatting / paragraphing slightly modified from the source for this answer.
对此答案的来源略有修改的格式/段落。
P.S. Don't be afraid of Exceptions!! They are friends!!!
PS 不要害怕例外!!他们是朋友!!!
回答by K Neeraj Lal
We pretty use much your same logic. Use try-catch
to prevent production apps from crashing.
我们几乎使用您相同的逻辑。使用try-catch
防止崩溃生产应用。
Exceptions should be NEVERignored. It is a bad coding practice. The guys maintaining the code will have a really hard time localizing the part of code that raised the exception if they are not logged.
异常应该从不忽略。这是一种糟糕的编码习惯。如果代码没有被记录,维护代码的人将很难定位引发异常的代码部分。
We use Crashlytics
to log the exceptions. The code will not crash (but some functionality will be disrupted). But you get the exception log in the dashboard of Fabric/Crashlytics
. You can look at these logs and fix the exceptions.
我们Crashlytics
用来记录异常。代码不会崩溃(但某些功能会中断)。但是您会在Fabric/Crashlytics
. 您可以查看这些日志并修复异常。
try {
codeThatCouldRaiseError();
} catch (Exception e) {
e.printStackTrace();
Crashlytics.logException(e);
}
回答by ChrisBrownie55
It's bad practice to use catch(Exception e){}
because you're essentially ignoring the error. What you probably want to do is something more like:
使用它是不好的做法,catch(Exception e){}
因为您基本上忽略了错误。您可能想要做的更像是:
try {
//run code that could crash here
} catch (Exception e) {
System.out.println(e.getMessage());
}
回答by Syzygy
I would put this as a comment to some other answer, but I don't have the reputation for that yet.
我会把它作为对其他答案的评论,但我还没有这方面的声誉。
You are correct in saying that it's bad practice, in fact what you posted shows different types of bad practice in regards to exceptions.
您说这是不好的做法是正确的,实际上您发布的内容显示了关于异常的不同类型的不良做法。
- Lack of error handling
- Generic Catch
- No intentional exceptions
- Blanket Try/catch
- 缺乏错误处理
- 通用渔获
- 没有故意的例外
- 毯子尝试/捕捉
I'll try to explain all of those via this example.
我将尝试通过这个例子来解释所有这些。
try {
User user = loadUserFromWeb();
if(user.getCountry().equals("us")) {
enableExtraFields();
}
fillFields(user);
} catch (Exception e) {
}
This can fail in several ways that should be handled differently.
这可能会以多种方式失败,应该以不同的方式处理。
- The fields will not be filled, so the user is presented with an empty screen and then... what? Nothing - lack of error handling.
- There's no distinction between different types of errors, e.g. Internet problems or problems with the server itself (outage, broken request, corrupted transmission, ...) - Generic catch.
- You can not use exceptions for your own purposes because the current system interferes with that. - No intentional exceptions
- Unessential and unexpected errors (e.g. null.equals(...)) can cause essential code not to execute. - Blanket try/catch
- 这些字段不会被填充,所以用户会看到一个空屏幕,然后……什么?没有 - 缺乏错误处理。
- 不同类型的错误之间没有区别,例如 Internet 问题或服务器本身的问题(中断、请求中断、传输损坏……) - 通用捕获。
- 您不能出于自己的目的使用异常,因为当前系统会干扰它。- 没有故意的例外
- 无关紧要的和意外的错误(例如 null.equals(...))会导致基本代码无法执行。- 毯子尝试/捕捉
Solutions
解决方案
(1) First of all, failing silently is not a good thing. If there's a failure, the app won't work. Instead there should be an attempt to resolve the problem or a display a warning, for example "Could not load user data, maybe you're not connected to the Internet?". If the app is not doing what it's supposed to, that's way more frustrating for a user than if it just closes itself.
(1)首先,默默地失败并不是一件好事。如果出现故障,该应用程序将无法运行。相反,应该尝试解决问题或显示警告,例如“无法加载用户数据,也许您没有连接到 Internet?”。如果应用程序没有做它应该做的事情,那对用户来说比直接关闭更令人沮丧。
(4) If the User is incomplete, e.g. the country is not known and returns null. The equals method will create a NullPointerException. If that NPE is just thrown and caught like above, the fillFields(user) method will not be called, even though it could still be executed without problems. You could prevent this by including null checks, changing execution order, or adjusting the try/catch scope. (Or you could do save coding like this: "us".equals(user.getCountry()), but I had to provide an example). Of course any other exception will also prevent fillFields() from being executed, but if there's no user, you probably don't want it executed anyway.
(4) 如果用户不完整,例如国家未知并返回空值。equals 方法将创建一个 NullPointerException。如果该 NPE 只是像上面那样被抛出和捕获,则不会调用 fillFields(user) 方法,即使它仍然可以毫无问题地执行。您可以通过包括空检查、更改执行顺序或调整 try/catch 范围来防止这种情况。(或者你可以像这样保存编码:“us”.equals(user.getCountry()),但我必须提供一个例子)。当然,任何其他异常也会阻止 fillFields() 被执行,但如果没有用户,您可能不希望它被执行。
(1, 2, 3)Loading from web often throws a variety of exceptions, from IOException to HttpMessageNotReadable exception to even just returning. Could be that the user isn't connected to the internet, could be that there was a change to a backend server or it is down, but you don't know because you do catch(Exception) - instead you should catch specific exceptions. You can even catch several of them like this
(1, 2, 3)从web加载经常会抛出各种各样的异常,从IOException到HttpMessageNotReadable异常甚至只是返回。可能是用户没有连接到互联网,可能是后端服务器发生了变化或者它已经关闭,但你不知道,因为你确实 catch(Exception) - 相反,你应该捕获特定的异常。你甚至可以像这样抓住其中的几个
try{
User user = loadUserFromWeb(); //throws NoInternetException, ServerNotAvailableException or returns null if user does not exist
if(user == null) {
throw new UserDoesNotExistException(); //there might be better options to solve this, but it highlights how exceptions can be used.
}
fillFields(user);
if("us".equals(user.getCountry()) {
enableExtraFields();
}
} catch(NoInternetException e){
displayWarning("Your internet conneciton is down :(");
} catch(ServerNotAvailableException e){
displayWarning("Seems like our server is having trouble, try again later.");
} catch(UserDoesNotExistException e){
startCreateUserActivity();
}
I hope that explains it.
我希望这能解释它。
At the very least as a quick fix, what you could do is send an event to your backend with the exception. For example through firebase or crashlytics. That way you can at least see stuff like (hey, the main activity does not load for 80% of our users due to a problem like (4).
至少作为一个快速修复,您可以做的是向您的后端发送一个异常事件。例如通过 firebase 或 crashlytics。这样你至少可以看到类似的东西(嘿,由于(4)之类的问题,我们 80% 的用户无法加载主要活动。
回答by PMar
While I agree with the other responses, there is one circumstance I have repeatedly encountered where this motif is marginally tolerable. Suppose someone wrote a bit of code for a class as follows:
虽然我同意其他回答,但在我反复遇到的一种情况下,这个主题是勉强可以容忍的。假设有人为一个类编写了一些代码,如下所示:
private int foo=0;
. . .
public int getFoo() throws SomeException { return foo; }
In this circumstance, the 'getFoo()' method cannot fail- there will always be a legitimate value of the private field 'foo' to be returned. Yet someone - probably for pedantic reasons - decided that this method should be declared as potentially throwing an Exception.If you then try to call this method in a context - e.g an event handler - which does not allow an exception to be thrown, you are basically forced to use this construct (even then, I agree that one should at least log the exception just in case). Whenever I have to do this, I always at least add a big fat comment 'THIS CANNOT OCCUR' next to the 'catch' clause.
在这种情况下,'getFoo()' 方法不会失败- 总会有一个合法的私有字段 'foo' 值被返回。 然而,有人——可能出于迂腐的原因——决定将此方法声明为可能引发异常。如果您随后尝试在不允许抛出异常的上下文(例如事件处理程序)中调用此方法,则您基本上被迫使用此构造(即使如此,我同意至少应该仅记录异常万一)。每当我必须这样做时,我总是至少在“catch”子句旁边添加一个大注释“这不能发生”。
回答by JoshG79
This is bad practice. Other answers have said that but I'd think it's important to step back and understand whywe have exceptions in the first place.
这是不好的做法。其他答案已经说过,但我认为退后一步并理解为什么我们首先会有例外是很重要的。
Every function has a post-condition– a set of things that must all be true after that function executes. For example, a function that reads from a file has the post condition that the data in the file will be read from disk and returned. An exception, then, is thrown when a function has not been able to satisfy one of its post-conditions.
每个函数都有一个后置条件——一组在该函数执行后必须全部为真的事情。例如,从文件读取的函数具有后置条件,即将从磁盘读取文件中的数据并返回。然后,当函数无法满足其后置条件之一时,将引发异常。
By ignoring an exception from a function (or even effectively ignoring it by simply logging the exception), you're saying that you're ok with that function not actually doing all the work it agreed to do. This seems unlikely – if a function does not run correctly, there is no guarantee that what follows will run at all. And if the rest of your code runs fine whether or not a particular function runs to completion, then one wonders why you have that function in the first place.
通过忽略函数中的异常(或者甚至通过简单地记录异常来有效地忽略它),您是在说您对该函数没有问题,实际上并没有完成它同意做的所有工作。这似乎不太可能——如果一个函数没有正确运行,就不能保证接下来的内容会运行。如果您的代码的其余部分运行良好,无论特定函数是否运行完成,那么人们首先会想知道为什么您有该函数。
[Now there are certain cases where empty catch
es are ok. For example, logging is something that you might justify wrapping in an empty catch. Your application will probably run fine even if some of the logging can't be written. But those are special cases that you have to work really hard to find in a normal app.]
[现在在某些情况下,空catch
es 是可以的。例如,日志记录是您可以证明包装在空捕获中的东西。即使无法写入某些日志记录,您的应用程序也可能会正常运行。但这些是特殊情况,您必须非常努力才能在普通应用程序中找到。]
So the point is, this is bad practice because it doesn't actually keep your app running (the supposed justification for this style). Maybe technically the OS hasn't killed it. But it's unlikely that the app is still running properly after simply ignoring an exception. And in the worst case, it could actually be doing harm (e.g. corrupting user files, etc.).
所以关键是,这是不好的做法,因为它实际上并没有让您的应用程序运行(这种风格的假设理由)。也许从技术上讲,操作系统并没有杀死它。但在简单地忽略异常后,应用程序不太可能仍然正常运行。在最坏的情况下,它实际上可能会造成伤害(例如损坏用户文件等)。