【问题标题】:How to catch exceptions listed in a throws clause如何捕获 throws 子句中列出的异常
【发布时间】:2014-07-26 11:08:06
【问题描述】:

如果我不写try/catchclause,如何捕获throws 子句中声明的异常?

  • 当我写这样的函数时

      public List<String> getTrackIds(int limit) throws NotConnectedException, UnauthorizedException {
              ...
         } 
    

这意味着函数可以抛出这些异常。但是不需要在 try/catch 块中捕获它吗?我将如何捕捉 这种情况下的例外情况?

  • 。当我尝试调用此函数时,必须编写 try/catch 块在调用中写一个throws 子句 功能。同样,如果我不写,我将如何捕获这些异常 尝试/捕获块?

【问题讨论】:

标签: java exception


【解决方案1】:

在例外情况下,您可以:

  • 使用try catch 块来处理它们。 (这是我的问题)
  • 在您的方法规范中使用throws 声明它们。 (不是我的问题,你自己处理)

对于后一种可能性,方法的调用者再次有相同的两个选项。如您所见,Exceptions 可以在您的程序流程中一直声明为throws。甚至 static void main(String[] args) 也可以使用这些 throws 子句声明,这最终意味着当声明的 Exception 之一被抛出时,您的应用程序将崩溃。


让我们看下面的例子:

/**
 * Throws a MyException.
 */
public static void methodThrowsException() throws MyException {
    throw new MyException();
}

/**
 * Calls methodThrowsException(), and handles the thrown MyException
 */
public static void myMethod() {
    try {
        methodThrowsException();
    } catch(MyException e) {
        /* Do something */
    }
}

/**
 * Calls methodThrowsException, but does not handle the thrown MyException.
 */
public static void mySecondMethod() throws MyException {
    methodThrowsException();
}

调用myMethodmySecondMethod 时,会发生以下情况:

public static void main(String[] args) {
    myMethod(); /* No catching needed */
    try {
        mySecondMethod();
    } catch(MyException e){
        /* Catching needed */
    }
}

如您所见,mySecondMethod 刚刚将捕获MyException 的问题转移给了它的调用者。

【讨论】:

  • 但是如果我只是在函数中使用 throws 子句,我将如何捕获异常?
  • 你没有,你让别人抓住他们(即方法的调用者)。不过,其他人可能再次成为您,您只是将捕获Exception 的问题转移到了另一个地方。
  • 好的。所以 throws 意味着我希望函数的调用者处理它。要么你抓住它,要么把它转移给其他人。
  • 确实如此。我已经编辑了答案以包含一个简单的示例。
  • 我不能再给 +1 了。很清楚的解释:)
【解决方案2】:

假设你有methodA,它被methodB调用,它被methodC调用,等等......


示例 1:

methodA 抛出 IOException。

然后 methodB 必须要么扔掉它,要么抓住它以结束投掷。 (假设它抛出它)。

因此 methodC 必须要么抛出它,要么抓住它(再说一次,假设它抛出它)。

可以说methodD实际上是主要方法。同样,您必须扔掉它或抓住它。如果你把它扔在这里,我们就在起点,没有地方可以扔它,所以这将停止程序执行。或者你可以抓住它。


示例 2:

methodA 抛出 IOException。

methodB 必须再次抓住它或扔掉它。这一次,它抓住了它。

methodC 不再需要抛出或捕捉它,因为它在 methodB 中处理。

【讨论】:

  • 这是一个很好的例子。我们可以通过捕获链中的异常来结束这个序列。
  • 正确。尽早在链中捕获它被认为是一种很好的做法。
  • 好的。我会做的。因为直到现在我还想再写一个 throws 子句,而不是思考如何捕捉它。
【解决方案3】:

您可能应该检查此链接以了解何时应处理异常(try-catch)以及何时应声明它们(使用 throws 子句):http://docs.oracle.com/javase/tutorial/essential/exceptions/catchOrDeclare.html

现在,回答你的问题——

但是不需要在 try/catch 块中捕获它吗?

并非总是如此。这取决于异常的类型。 Java 有两种异常类型:CheckedUnchecked。而Error 是一种运行时情况,无法从中恢复 在此处阅读更多信息http://docs.oracle.com/javase/tutorial/essential/exceptions/

对于可能引发检查异常的代码,您MUST 提供以下之一:

  1. try-catch 块
  2. 方法声明中的 throws 子句

对于可能引发未经检查的异常的代码,编译器不会强制您处理或声明它们。不过,如果你愿意,你可以做其中之一。

在这种情况下我将如何捕获异常?

在您的情况下,NotConnectedExceptionUnauthorizedException 都是未经检查的异常。所以你可以(但不是由编译器强制)在你的方法代码中编写 try-catch 块,或者你可以在 throws 子句中声明它们。当您在 throws 子句中声明它们时,方法的调用者知道这些异常 MAY 会从中抛出,并计划编写自己的 try-catch 以在其端进行异常处理。

当我尝试调用此函数时,必须在调用函数中编写 try/catch 块或编写 throws 子句。

正如我所提到的,这两个异常都是未经检查的(继承自 RuntimeException),因此您也不需要这样做。但你可以做其中之一。

同样,如果我不编写 try/catch 块,我将如何捕获这些异常?

你没有。方法的调用者必须使用他们自己的 try-catch 来计划异常处理。

【讨论】:

    【解决方案4】:

    try ... catch (甚至 finally :) ) 块应该在调用者方法中。
    调用者方法例如是:

    public void handleTracks() {
    
     int limit = 100;
     try {
        List<String> trackIds = getTrackIds(trackIds);
     } catch (NotConnectedException ex) {
       System.err.println("No connection was established to the tacks system. Please perform login").
     } catch (UnauthorizedException ex) {
        System.err.println("The user is unauthorized to handle the track").
     }
    }
    

    如您所见,对各种异常类型有不同的处理方式
    如果需要,并且您使用的是 JDK 7 及更高版本,您可以让 catch 块看起来像:

    } catch (UnauthorizedException | NotConnectedException ex) {
        System.err.println("An error").
     }
    

    这在您的方法抛出多个异常的情况下很有用,并且您希望对 2 个或更多异常进行相同的处理,而对其他异常进行不同的处理。

    另一种选择当然是只有一个

     catch (Exception ex) {
        System.err.println("An error").
     }
    

    但这将捕获所有异常,包括已声明和未声明(即使未在签名的 throws 部分声明,该方法仍可能抛出运行时异常)。

    希望这会有所帮助。

    【讨论】:

      【解决方案5】:

      有3种异常

      1. 语法错误:编译错误
      2. 逻辑错误:-运行时
      3. 运行时错误:运行时(最危险的错误)

      这里1和2可以由程序员手动解决。

      而当出现运行时错误时,例如:- 用户输入 1/0,这是一个异常,并且 1000 行代码在那一刻就付诸东流了。

      所以 java 开发人员想他们将如何解决这类问题。 所以他们介绍了两件事:-

      1. 抛出
      2. 终于尝试抓住了。

      所以java中有2种异常

      1. 已检查(您将始终需要已检查异常的处理程序)
      2. 未选中

      现在让我们谈谈 throws 的工作原理:-

      Throws 永远不会捕获异常。它只是告诉 jvm 它包含异常并且 jvm 应该忽略此异常。 现在我知道你会想如果代码中有一些异常,jvm 将如何处理它。 jvm 会在运行时抛出异常。您只能将 throws 与选中的 execption 一起使用。

      而在 try catch 中,Try 块将查看是否有任何可以捕获的异常,然后将其捕获并运行进一步的代码。方法的调用者必须使用自己的 try 计划异常处理-抓住。

      【讨论】:

      • 其实就是把它传递给函数的调用者。请查看已接受的答案。
      【解决方案6】:

      我想我会添加另一个使用自定义异常的示例,它可能有助于进一步了解异常的使用方式以及所有内容如何组合在一起。在计算器程序中,我有一个 ValidationException:

      public class ValidationException extends Exception {
      
          public ValidationException(String msg){
              super(msg);
          }
      
      }
      

      我有一个控制器,它将数学总和作为字符串。 IE。它将类似于“(2 + 2) - 1 * 3”。

      在计算答案之前,它会进入验证器以检查总和是否有效(它会检查总和中是否有字母,检查其不为空,检查是否有两个相邻的数学运算符等.).

      public class Validator {
      
          public void check(String sum) throws ValidationException{
              checkForNull(sum);
              checkForLetters(sum);
          }
      
          private void checkForNull(String sum) throws ValidationException{
              if(sum==null || sum.equals("")){
                  throw new ValidationException("You must enter a sum");
              }
          }
      
      
          private void checkForLetters(String sum) throws ValidationException {
              if(.......){
                  throw new ValidationException("The sum cannot contain letters");
              }
          }
      
      }
      

      然后控制器的句柄是这样的:

      public void handle(){
      
          String sum = view.getSumFromUser();
          try{
              validator.check(sum);
              String answer = calculator.calculate(sum);
              view.outputResponse("The answer is " + answer);
          } catch (ValidationException ex){
              view.outputResponse(ex.getMessage());
          }
      
      }
      

      在最后一种方法中,calculator.calculate(sum) 仅在 validator.check(sum) 无异常完成时运行。

      如果有异常,用户会收到异常消息。

      【讨论】:

        猜你喜欢
        • 2015-07-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-17
        相关资源
        最近更新 更多