问题 抛出异常处理中的子句


我已经阅读了数百篇有关此事的帖子,但我仍不清楚这一点。

  • 当我写这样的功能

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

这意味着该函数可以抛出这些异常。但是不是需要在try / catch块中捕获它吗?我怎么会抓到     在这种情况下例外?

  • 。当我尝试调用此函数时,则强制写入            尝试/捕获块 要么 写一个 throws 呼唤中的条款            功能。再次,如果我不写一个,我将如何捕获这些例外            try / catch块?

12762
2017-07-26 11:08


起源

正如我在下面的回答中提到的,您还应该查看此链接以了解 Catch or Specify 需求: docs.oracle.com/javase/tutorial/essential/exceptions/... - Pat
谢谢@Pat。我当然读了。然后我在我仍有疑虑之后发布了我的问题。 - Diffy


答案:


使用例外,您可以:

  • 使用 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();
}

打电话的时候 myMethod 要么 mySecondMethod,发生以下情况:

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

如你看到的, mySecondMethod 刚刚转移了赶上的问题 MyException 给它的来电者。


8
2017-07-26 11:10



但是,如果我只使用带有该函数的throws子句,我将如何捕获异常? - Diffy
你没有,你让别人抓住他们(即方法的来电者)。但是,其他人可能会再次成为你,你刚刚解决了这个问题 Exception 到另一个地方。 - nhaarman
好的。因此抛出意味着我希望函数的调用者处理它。您可以抓住它或将其转移给其他人。 - Diffy
确实。我编辑了答案,包括一个简单的例子。 - nhaarman
我不能给+1更多。很清楚的解释:) - Keerthivasan


假设你有methodA,它被methodB调用,由methodC调用,依此类推......


例1:

methodA抛出IOException。

然后,methodB也必须抛出它,或者捕获它以结束投掷。 (让我们说它抛出它)。

因此,methodC必须抛出它或捕获它(再次,假设它抛出它)。

让我们说methodD实际上是主要的方法。再一次,你必须扔它或抓住它。如果你把它扔到这里,我们就处于起点,无处可去,所以这将阻止程序的运行。或者你可以抓住它。


例2:

methodA抛出IOException。

methodB再次必须捕获它或抛出它。这一次,它抓住了它。

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


2
2017-07-26 11:19



这是一个很好的例子。我们可以通过捕获链中的exeption来结束这个序列。 - Diffy
正确。并且尽可能早地在链中捕捉它是一种良好的做法。 - Chris
好。我会做的。因为到现在为止我只想写另一个抛出条款,而不是想如何抓住它。 - Diffy


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

现在,回答你的问题 -

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

不总是。这取决于异常的类型。 Java有两种类型的异常: Checked 和 Unchecked。和 Error 是无法恢复的运行时情况在此处阅读更多相关信息 http://docs.oracle.com/javase/tutorial/essential/exceptions/

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

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

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

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

在你的情况下,两者 NotConnectedException 和 UnauthorizedException 是未经检查的例外情况。所以你可以(但不是被编译器强制)在你的方法代码中编写try-catch块,或者你可以在throws子句中声明它们。当您在throws子句中声明它们时,该方法的调用者知道这些异常 MAY 被抛出并计划在他们的最后编写自己的try-catch用于异常处理。

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

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

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

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


2
2017-07-26 11:22





try ... catch(甚至最后:))块应该是调用方法。
调用方法例如是:

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部分声明,仍然可能由方法抛出的运行时异常)。

希望这可以帮助。


0
2017-07-26 11:27





有3种例外

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

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

而当存在运行时错误时,例如: - 用户输入1/0这是一个例外,1000行代码在那个时刻流失。

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

  1. 最后试试。

所以java中有两种类型的异常

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

现在让我们谈谈投掷的工作方式: -

投掷从未捕获异常。它只是告诉jvm它包含异常,jvm应该忽略这个异常。 现在我知道你会想到如果代码中有一些异常,jvm将如何处理它。 jvm将在运行时抛出异常。您只能对已检查的execption使用throws。

而在try catch中,Try块将查看是否存在可以捕获的异常,然后捕获该异常,并且可以运行更多代码。该方法的调用者必须使用自己的try-catch计划异常处理。


0
2017-07-26 11:12



它实际上意味着将它传递给函数的调用者。请参阅接受的答案。 - Diffy


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

public class ValidationException extends Exception {

    public ValidationException(String msg){
        super(msg);
    }

}

我有一个控制器,它将数学和作为一个字符串。即它会像“(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());
    }

}

在最后一个方法中,如果validator.check(sum)完成且没有异常,则仅运行calculator.calculate(sum)。

如果存在异常,则用户获取异常消息。


0
2017-07-26 11:48