Java - 如何正确处理try catch块

时间:2016-07-03 01:08:11

标签: java try-catch

我想知道处理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);

或者这是不好的做法?

3 个答案:

答案 0 :(得分:2)

异常处理不是做出草率假设的地方;通常在你执行这部分代码的时候,这是因为发生了一些意料之外的事情,这时你需要非常小心地准确地检测和记录发生的事情,这样你才能知道需要解决的问题。

选择Exception作为被捕获的异常类型过于宽泛。您正在调用的方法会因为截然不同的原因而抛出3个不同的异常;其中只有一个是应该在这里捕获的东西。此外,NullPointerException等未经检查的异常也会被捕获。如果你要在这个无意中引入NPE的catch块中添加一些代码,那么就很难弄清楚出了什么问题。您的过度捕获可能导致无法找到错误或错误无法正确处理。

(Btw Makoto说得好,无论如何,nextInt不是你应该在这里打电话的。)

在您确定异常意味着什么的狭窄情况下(例如,如果您在Makoto的示例代码中捕获了InputMismatchException或NumberFormatException),不能记录异常是可以接受的。但结合捕获异常,它有能力隐藏错误并引起混淆。

你可能选择捕捉异常,因为处理一堆不同的已检查异常,其中大部分似乎不太可能发生,似乎是一种无法容忍的麻烦。通过为不知道如何处理的异常提供合理的默认情况,提供一致的处理和记录异常的方法将有所帮助。这样,如果你看到一个你无法处理的异常,你总是可以选择让它被抛出(可能会捕获它并将其包装在未经检查的异常中),知道如果抛出它将被记录并结束你的程序。

对于一个非常小的命令行程序,有时完全可以让你无法处理的异常从main抛出(通过向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);
    }
}

任何一种替代方案都会让你不恰当地吞下不方便的检查异常。

答案 1 :(得分:1)

简单回答:你写的很好

更长的答案:try-catch块用于执行可能抛出异常的代码,然后处理所述异常(如果发生)。通常,catch块应该具有处理异常的代码,但是您需要处理它。如果您当前拥有的陈述是您希望如何回应异常,那么按照惯例它就没问题了。 catch块中常见的一些事情是:

  • 抛出另一个封装抛出异常的异常。 (我经常在解析时这样做,以便可以有一个ParseException)
  • 抛出一个封装抛出异常的运行时异常,让java默认的未捕获异常处理程序处理它。 (当我编写快速临时程序并且我不想处理已检查的异常时,我会这么做很多)
  • 将其传递给程序中的某个通用处理程序,例如显示错误的GUI等。
  • 打电话给printStacktrace

但是任何符合你的异常处理需求的东西都很好

答案 2 :(得分:1)

实际上,这段代码不会按照你想要的方式运行。这有两个关键原因:

  • nextInt()阻塞,直到收到整数;也就是说,在读取整数之前,它不会关心你给它的输入,并且
  • 即使这样做也没关系,取决于您初始化userNthpiDecimals的方式,可能无法定义其中一个或两个变量,从而阻止了编译。

此外,不会抓住Exception在捕获异常时尽可能具体,因为Exception还包含一些漂亮而危险的RuntimeExceptionNullPointerException一样。

您要做的事情:

  • 接受整数输入
  • 如果用户输入非整数,请告诉他们需要输入整数
  • userNth < 1 || userNth > piDecimals
  • 期间继续这样做

为此,我们应该通过将输入解析为字符串 first 然后作为{{}来获取正确的异常。 1}}:

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并未涵盖此消息。这,我作为练习留给读者。