[英]Java - How to properly handle a try catch block
I was wondering what is the proper convention for handling a try/catch block. 我想知道什么是处理try / catch块的正确约定。 It is pretty obvious what should be within the
try
block but what about the catch
block? 很明显,
try
块中应该包含什么,但是catch
块又如何呢?
Can I write a message to the user like the following: 是否可以向用户发送如下消息:
do {
try {
System.out.println("Pi to the number of decimal places:");
Scanner in = new Scanner(System.in);
userNth = in.nextInt();
} catch (Exception e) {
System.out.println("Error: Enter a number between 1 and 100");
}
} while(userNth < 1 || userNth > piDecimals);
Or is this bad practice? 还是这是不好的做法?
Exception-handling is not the place to make rash assumptions; 异常处理不是做出粗鲁假设的地方; usually by the time this part of your code has been executed it's because something unanticipated has happened, this is when you want to be most careful to be accurate about detecting and recording what happened so that you can tell what needs fixing.
通常,在执行这部分代码时,是因为发生了意外的情况,这时您要非常小心地准确地检测和记录发生的事情,以便知道需要解决的问题。
The choice of Exception as the type of exception that gets caught is too broad. 将Exception作为捕获的异常类型的选择范围太广。 The method you're calling throws 3 different exceptions for distinctly different reasons;
您正在调用的方法由于明显不同的原因而引发3个不同的异常。 only one of which is something that should be caught here.
只有其中一项是应该在这里捕获的。 Also unchecked exceptions like NullPointerException will get caught by this.
同样,诸如NullPointerException之类的未经检查的异常也会被此捕获。 If you were to add some code to this catch block that inadvertently introduced a NPE it would be hard to figure out what went wrong.
如果要在此catch块中添加一些代码,而无意中引入了NPE,则很难弄清楚出了什么问题。 Your overbroad catch can result in bugs not being found or errors not getting handled properly.
过度捕获可能导致找不到错误或未正确处理错误。
(Btw Makoto makes a good point that nextInt isn't what you should be calling here anyway.) (顺便说一句,Bakto Makoto很好地指出,无论如何,nextInt都不是您应该在这里所说的。)
Not logging the exception can be acceptable in narrow cases where you're certain of what the exception means (for instance, if you caught InputMismatchException, or NumberFormatException in Makoto's example code). 在确定异常含义的狭义情况下(例如,如果在Makoto的示例代码中捕获了InputMismatchException或NumberFormatException),不记录异常是可以接受的。 But in combination with catching Exception it has the capacity to hide errors and cause confusion.
但是结合捕获Exception,它可以隐藏错误并引起混乱。
You likely chose to catch Exception because handling a bunch of different checked exceptions, most of which seemed unlikely to ever happen anyway, seemed like an intolerable nuisance. 您可能选择捕获Exception是因为处理大量不同的已检查异常,这些异常似乎无论如何都不会发生,似乎令人无法忍受。 Providing a consistent way of handling and logging exceptions will help, by providing a reasonable default case for exceptions you don't know what to do with.
通过为您不知道如何处理的异常提供合理的默认情况,提供一致的处理和记录异常的方式将有所帮助。 That way if you see an exception you just can't handle, you always have the option of letting it be thrown (possibly catching it and wrapping it in an unchecked exception), knowing that if thrown it will get logged and end your program.
这样,如果您看到无法处理的异常,则始终可以选择引发该异常(可能是捕获该异常并将其包装在未经检查的异常中),知道如果引发该异常将被记录并结束程序。
For a very small command-line program sometimes it's entirely ok to let exceptions that you can't handle be thrown from main (by adding throws Exception to the main method). 对于很小的命令行程序,有时完全可以将无法处理的异常从main中抛出(通过将throws Exception添加到main方法中)。 This is ok for toy examples, small school projects, etc.;
可以用于玩具示例,小型学校项目等; I'd only use it in production code if there was a plan for logging the output (like a batch file that redirects stderr to a file):
如果有计划记录输出(例如将stderr重定向到文件的批处理文件),则仅在生产代码中使用它:
public static void main(String... args) throws Exception {
... application code
}
In most cases all the main method code should be placed in a try block where any Throwable is caught and logged: 在大多数情况下,所有主要方法代码都应放置在try块中,在其中捕获并记录任何Throwable:
public static void main(String... args) {
try {
... application code here
}
catch (Throwable t) {
logger.log(t);
}
}
Either alternative makes it less tempting for you to inappropriately swallow inconvenient checked exceptions. 两种选择都可以使您减少不适当地吞咽不便的检查异常的诱因。
Simple Answer: what you wrote is fine 简单的答案:你写的很好
Longer Answer: try-catch blocks are for executing code that may throw an exception, and then handling said exception if it occurs. 更长的答案:try-catch块用于执行可能引发异常的代码,然后在发生异常时对其进行处理。 In general, the catch block should have code that handles the exception however you need to handle it.
通常,catch块应具有处理异常的代码,但是您需要对其进行处理。 If the statement you currently have is how you want to respond to an exception, then it's fine by convention.
如果您当前拥有的语句是您希望如何响应异常,那么按惯例就可以了。 Some common things to do in a catch block are:
在catch块中要做的一些常见事情是:
printStacktrace
on it printStacktrace
But anything that fits your exception-handling needs is fine 但是任何符合您的异常处理需求的方法都可以
In all actuality, this code is not going to function the way you intend it to. 实际上,此代码不会按您预期的方式起作用。 There are two key reasons for this:
造成这种情况的主要原因有两个:
nextInt()
blocks until it receives an integer; nextInt()
阻塞直到接收到整数; that is, it's not going to care about what input you give it until it reads an integer, and userNth
and piDecimals
, one or both of those variables may not be defined, thus preventing compilation. userNth
和piDecimals
,也可能未定义其中一个或两个变量,从而阻止了编译。 Also, don't catch Exception
. 另外, 不要捕获
Exception
。 Be as specific as you can when catching exceptions, since Exception
also includes some nifty and dangerous RuntimeException
s like NullPointerException
. 捕获异常时,请尽可能具体,因为
Exception
还包括一些漂亮而危险的RuntimeException
例如NullPointerException
。
What you're looking to do: 您要做什么:
userNth < 1 || userNth > piDecimals
userNth < 1 || userNth > piDecimals
时继续执行此userNth < 1 || userNth > piDecimals
userNth < 1 || userNth > piDecimals
. userNth < 1 || userNth > piDecimals
。 To that, we should look to get the right exception thrown by parsing the input as a string first , then as an Integer
: 为此,我们应该通过首先将输入解析为字符串, 然后解析为
Integer
抛出正确的异常:
try {
System.out.println("Pi to the number of decimal places:");
userNth = Integer.parseInt(in.nextLine());
} catch (NumberFormatException e) {
System.out.println("Error: Enter a number between 1 and 100");
// You have to set this value to something so that userNth is defined!
userNth = Integer.MAX_VALUE;
}
The other part to this is that you have to decide what message you show if userNth > 1 && userNth < piDecimals
, since your try...catch
isn't going to cover that. 另一部分是,如果
userNth > 1 && userNth < piDecimals
,则必须决定显示什么消息,因为try...catch
不会覆盖该内容。 This, I leave as an exercise for the reader. 这,我留给读者练习。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.