约书亚·布洛赫在《有效的Java》中说过

为以下情况使用检查异常 可恢复条件和运行时 编程错误的例外 (第二版第58项)

看看我理解的对不对。

以下是我对受控异常的理解:

try{
    String userInput = //read in user input
    Long id = Long.parseLong(userInput);
}catch(NumberFormatException e){
    id = 0; //recover the situation by setting the id to 0
}

1. 上述异常是否被认为是受控异常?

2. RuntimeException是未检查的异常吗?

以下是我对未检查异常的理解:

try{
    File file = new File("my/file/path");
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){

//3. What should I do here?
    //Should I "throw new FileNotFoundException("File not found");"?
    //Should I log?
    //Or should I System.exit(0);?
}

4. 现在,上面的代码不能也是一个受控异常吗?我可以试着挽回这样的局面吗?我可以吗?(注:我的第三个问题在上面的陷阱里)

try{
    String filePath = //read in from user input file path
    File file = new File(filePath);
    FileInputStream fis = new FileInputStream(file);   
}catch(FileNotFoundException e){
    //Kindly prompt the user an error message
    //Somehow ask the user to re-enter the file path.
}

5. 人们为什么要这样做?

public void someMethod throws Exception{

}

为什么他们让异常冒出来?早点处理错误不是更好吗?为什么要冒出来?

6. 我是否应该冒泡出确切的异常或使用异常掩盖它?

以下是我的阅读资料

在Java中,什么时候应该创建检查异常,什么时候应该是运行时异常?

何时选择已检查异常和未检查异常


当前回答

受控异常在编译时由JVM检查,并与资源相关(文件/db/流/套接字等)。受控异常的动机是,在编译时,如果资源不可用,应用程序应该在catch/finally块中定义一个替代行为来处理这个异常。

未经检查的异常纯粹是编程错误、错误计算、空数据甚至业务逻辑中的失败都可能导致运行时异常。在代码中处理/捕获未检查的异常是绝对没问题的。

解释摘自http://coder2design.com/java-interview-questions/

其他回答

为了回答最后一个问题(上面的其他问题似乎都得到了彻底的回答),“我应该冒泡出确切的异常还是使用exception掩盖它?”

我猜你的意思是这样的:

public void myMethod() throws Exception {
    // ... something that throws FileNotFoundException ...
}

不,总是声明尽可能精确的异常,或者一个这样的列表。你声明你的方法能够抛出的异常是你的方法和调用者之间契约的一部分。抛出"FileNotFoundException"意味着可能文件名无效,无法找到该文件;调用者需要聪明地处理这个问题。抛出异常意味着“嘿,该死的事情发生了。交易。”这是一个非常糟糕的API。

在第一篇文章的注释中有一些例子,其中“throws Exception”是一个有效且合理的声明,但对于您所编写的大多数“正常”代码来说,情况并非如此。

所有这些都是受控异常。未检查的异常是RuntimeException的子类。问题不在于如何处理它们,而在于你的代码是否应该抛出它们。如果你不想让编译器告诉你你还没有处理一个异常,那么你可以使用一个未检查的(RuntimeException的子类)异常。这些应该保存在你无法恢复的情况下,比如内存不足等。

这里有一个简单的规则可以帮助你做出决定。它与Java中如何使用接口有关。

以你的类为例,想象一下为它设计一个接口,该接口描述类的功能,但不描述底层实现(接口应该这样)。假设您可能以另一种方式实现该类。

查看接口的方法,并考虑它们可能抛出的异常:

如果方法可以抛出异常,而不管底层实现是什么(换句话说,它只描述功能),那么它可能应该是接口中的受控异常。

如果异常是由底层实现引起的,那么它不应该出现在接口中。因此,它必须是类中的未检查异常(因为未检查异常不需要出现在接口签名中),或者必须将其包装并作为接口方法的一部分的已检查异常重新抛出。

To decide if you should wrap and rethrow, you should again consider whether it makes sense for a user of the interface to have to handle the exception condition immediately, or the exception is so general that there is nothing you can do about it and it should propagate up the stack. Does the wrapped exception make sense when expressed as functionality of the new interface you are defining or is it just a carrier for a bag of possible error conditions that could also happen to other methods? If the former, it might still be a checked exception, otherwise it should be unchecked.

通常不应该计划“冒泡”异常(捕获并重新抛出)。异常要么应该由调用者处理(在这种情况下它被检查),要么应该一直向上到高级处理程序(在这种情况下,如果它不被检查是最简单的)。

1 . 如果你不确定一个异常,检查API:

java . lang . object 由java.lang.Throwable扩展 由java.lang.Exception扩展 //<-NumberFormatException是一个RuntimeException 由java.lang.IllegalArgumentException扩展 由java.lang.NumberFormatException扩展

2。是的,以及所有扩展它的异常。

3.不需要捕获和抛出相同的异常。在这种情况下,您可以显示一个新的文件对话框。

4所示。FileNotFoundException已经是一个检查异常。

5。如果期望调用someMethod的方法捕获异常,则可以抛出后者。它只是“传球”。使用它的一个例子是,如果你想在你自己的私有方法中抛出它,而在你的公共方法中处理异常。

一个很好的阅读是Oracle文档本身:http://download.oracle.com/javase/tutorial/essential/exceptions/runtime.html

Why did the designers decide to force a method to specify all uncaught checked exceptions that can be thrown within its scope? Any Exception that can be thrown by a method is part of the method's public programming interface. Those who call a method must know about the exceptions that a method can throw so that they can decide what to do about them. These exceptions are as much a part of that method's programming interface as its parameters and return value. The next question might be: "If it's so good to document a method's API, including the exceptions it can throw, why not specify runtime exceptions too?" Runtime exceptions represent problems that are the result of a programming problem, and as such, the API client code cannot reasonably be expected to recover from them or to handle them in any way. Such problems include arithmetic exceptions, such as dividing by zero; pointer exceptions, such as trying to access an object through a null reference; and indexing exceptions, such as attempting to access an array element through an index that is too large or too small.

在Java语言规范中还有一些重要的信息:

在throws子句中命名的受控异常类是方法或构造函数的实现者和用户之间契约的一部分。

IMHO的底线是,您可以捕获任何RuntimeException,但不需要这样做,事实上,实现不需要维护抛出的相同的未检查异常,因为这些异常不是契约的一部分。

如果有人想要另一个不喜欢受控异常的证明,请参阅流行JSON库的前几段:

虽然这是一个受控异常,但它很少是可恢复的。大多数调用方应该简单地将此异常包装在未检查的异常中并重新抛出:"

那么,如果我们应该“简单地包装它”,为什么世界上有人会让开发人员不断检查异常呢?哈哈

http://developer.android.com/reference/org/json/JSONException.html