繁体   English   中英

Java-如何正确处理try catch块

[英]Java - How to properly handle a try catch block

我想知道什么是处理try / catch块的正确约定。 很明显, try块中应该包含什么,但是catch块又如何呢?

是否可以向用户发送如下消息:

       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);

还是这是不好的做法?

异常处理不是做出粗鲁假设的地方; 通常,在执行这部分代码时,是因为发生了意外的情况,这时您要非常小心地准确地检测和记录发生的事情,以便知道需要解决的问题。

将Exception作为捕获的异常类型的选择范围太广。 您正在调用的方法由于明显不同的原因而引发3个不同的异常。 只有其中一项是应该在这里捕获的。 同样,诸如NullPointerException之类的未经检查的异常也会被此捕获。 如果要在此catch块中添加一些代码,而无意中引入了NPE,则很难弄清楚出了什么问题。 过度捕获可能导致找不到错误或未正确处理错误。

(顺便说一句,Bakto Makoto很好地指出,无论如何,nextInt都不是您应该在这里所说的。)

在确定异常含义的狭义情况下(例如,如果在Makoto的示例代码中捕获了InputMismatchException或NumberFormatException),不记录异常是可以接受的。 但是结合捕获Exception,它可以隐藏错误并引起混乱。

您可能选择捕获Exception是因为处理大量不同的已检查异常,这些异常似乎无论如何都不会发生,似乎令人无法忍受。 通过为您不知道如何处理的异常提供合理的默认情况,提供一致的处理和记录异常的方式将有所帮助。 这样,如果您看到无法处理的异常,则始终可以选择引发该异常(可能是捕获该异常并将其包装在未经检查的异常中),知道如果引发该异常将被记录并结束程序。

对于很小的命令行程序,有时完全可以将无法处理的异常从main中抛出(通过将throws Exception添加到main方法中)。 可以用于玩具示例,小型学校项目等; 如果有计划记录输出(例如将stderr重定向到文件的批处理文件),则仅在生产代码中使用它:

public static void main(String... args) throws Exception {
    ... application code
}

在大多数情况下,所有主要方法代码都应放置在try块中,在其中捕获并记录任何Throwable:

public static void main(String... args) {
    try {
        ... application code here
    }
    catch (Throwable t) {
        logger.log(t);
    }
}

两种选择都可以使您减少不适当地吞咽不便的检查异常的诱因。

简单的答案:你写的很好

更长的答案:try-catch块用于执行可能引发异常的代码,然后在发生异常时对其进行处理。 通常,catch块应具有处理异常的代码,但是您需要对其进行处理。 如果您当前拥有的语句是您希望如何响应异常,那么按惯例就可以了。 在catch块中要做的一些常见事情是:

  • 引发另一个封装了引发的异常的异常。 (我经常在解析时执行此操作,以便可以有一个ParseException)
  • 抛出封装了抛出异常的运行时异常,并让Java的默认未捕获异常处理程序处理该异常。 (在编写快速的临时程序并且不想处理检查的异常时,我经常这样做。)
  • 将其传递给程序中的某些通用处理程序,例如用于显示错误的GUI等。
  • 调用printStacktrace

但是任何符合您的异常处理需求的方法都可以

实际上,此代码不会按您预期的方式起作用。 造成这种情况的主要原因有两个:

  • nextInt()阻塞直到接收到整数; 也就是说,在读取整数之前,它不会关心您提供的输入,并且
  • 即使可以,根据您初始化userNthpiDecimals ,也可能未定义其中一个或两个变量,从而阻止了编译。

另外, 不要捕获Exception 捕获异常时,请尽可能具体,因为Exception还包括一些漂亮而危险的RuntimeException例如NullPointerException

您要做什么:

  • 接受整数输入
  • 如果用户输入非整数,则告诉他们他们需要输入整数
  • userNth < 1 || userNth > piDecimals时继续执行此userNth < 1 || userNth > piDecimals userNth < 1 || userNth > piDecimals

为此,我们应该通过首先将输入解析为字符串, 然后解析为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;
}

另一部分是,如果userNth > 1 && userNth < piDecimals ,则必须决定显示什么消息,因为try...catch不会覆盖该内容。 这,我留给读者练习。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM