没有任何catch语句的Try块

8

我在阅读一本关于异常和断言的Java教材时,遇到了下面这段代码,并有一个问题。

public boolean searchFor(String file, String word)
    throws StreamException
{
    Stream input = null;

    try {
        input = new Stream(file);
        while (!input.eof())
            if (input.next().equals(word))
                return true;
        return false;         //not found
    } finally {
        if (input != null)
            input.close();
    }
}

在下一段中,文本说“searchFor方法声明它会抛出StreamException,这样任何生成的异常都会在清理之后传递给调用代码,包括由关闭调用引发的任何StreamException。”
我原以为包含throws子句是允许程序员抛出特定类(或子类)异常的方式,只有在throws子句中包含它或其超类时才能抛出该类。但在这里,try块中没有throw语句的throws子句。那么首先包括该子句的目的是什么?在代码中哪里可以捕获StreamException异常?

2
如果代码抛出异常,finally块仍将被执行。异常将从该方法中抛出。 - WalterM
@WalterM但我认为在throws子句中包含异常的重点是使编译器允许您具有特定的catch语句,并引用可能抛出的不同类型的异常。如果可以在没有catch语句的情况下抛出已检查异常,那么具有catch语句的意义何在? - UnworthyToast
可能是Java Try Catch Finally blocks without Catch的重复问题。 - Raedwald
6个回答

8

在代码中哪里可以捕获StreamException

try块中有一个finally,但没有catchfinally会执行,而Exception会传播到调用者


啊!是的,我想我忘记了一个异常会继续向外搜索匹配其类型的catch语句,如果在第一个块中没有找到。现在它更有意义了。谢谢! - UnworthyToast
4
正如Nathan的答案所指出的,try-with-resources语句在不掩盖finally块中的任何异常方面具有额外的优势(我认为您的书可能早于try-with-resources的推出)。请参阅try-with-resources语句 - Elliott Frisch
我正在阅读《Java编程语言》第四版。在索引中,我只看到了try-catchtry-catch-finallytry-finally。所以,它肯定是早于try-with-resources语句的。我会去了解一下这个内容。 - UnworthyToast

5
重点是确保流被关闭,无论方法中发生了什么。在迭代流时抛出的任何异常都会传递给调用者。(每个调用者都可以选择捕获异常或将其传递给其调用者,以此类推。)如果此代码使用try-with-resources,则可以确保在迭代流时抛出的异常不会掩盖关闭时抛出的异常。(如果关闭方法抛出异常,则调用者将看到它,即使尝试块中有其他异常抛出。)

2
如果我没记错的话,StreamException不会在这个类中被处理,而是在一个带有catch (StreamException se) {...}的类中被处理,也就是调用者。
无论是否抛出异常,finally块都将始终执行,因此它将始终关闭流。
你可以有三种不同类型的try块:
  1. try-catch(尝试或捕获块将被执行)
  2. try-catch-finally(尝试或捕获块将被执行,并且无论如何最终块都将执行)
  3. try-finally(两个块都将被执行)

从Java 8开始,还有一个try-with块可以优雅地处理此问题。 - hubatish
@hubatish,如果您能给出一个示例,我会很高兴看到您的答案,因为我从未尝试过 :) - Frakcool

1
请注意,如果没有捕获异常,异常仍将逃离代码块:
try {
    try {
        System.out.println('0');
        int i = 100 / 0; // throw an exception
    } finally {
        System.out.println('1');
    }
    System.out.println('2');
} catch (Exception e) {
    System.out.println('3');
}

输出: 0 1 3


0
Java 7 引入了 try-with-resources 语句,完美地处理了这种情况。
public boolean searchFor(String file, String word)
    throws StreamException
{
    try (Stream input = new Stream(file)) {
        while (!input.eof()) {
            if (input.next().equals(word)) {
                return true;
            }
        }
        return false;         //not found
    }
}

这段代码与你的示例相同,并适用于任何实现了AutoCloseable接口的对象。

对于那些替换代码的人来说,需要注意一点:在try块和try-with语句或finally块中抛出异常时,返回的异常和被压制的异常有一些小差异。详见Oracle文档


0

throws SomeException 跟在方法签名后面的代码,意味着在该方法块内编写的某些代码可能会抛出编译时异常。

根据 Java 的 exception 规则,当抛出任何 compile-time exception 时,需要声明或处理它。

在您的代码中没有编写任何 throw 语句,但是块中的某些方法调用需要 handle or declare 它。

throws Exception would propagate to the invoker.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接