约书亚·布洛赫在《有效的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中,什么时候应该创建检查异常,什么时候应该是运行时异常?

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


当前回答

已检查-容易发生。在编译时选中。

小薇。FileOperations

未检查-由于不良数据。在运行时签入。

如. .

String s = "abc";
Object o = s;
Integer i = (Integer) o;

Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at Sample.main(Sample.java:9)

这里的异常是由于错误的数据,在编译时无法确定。

其他回答

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

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

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

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

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

我猜你的意思是这样的:

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

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

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

这里有一个简单的规则可以帮助你做出决定。它与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.

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

许多人说检查异常(即你应该显式地捕获或重新抛出的异常)根本不应该使用。例如,它们在c#中被淘汰了,大多数语言都没有它们。因此,您总是可以抛出RuntimeException的子类(未检查的异常)

然而,我认为受控异常是有用的——当你想强迫API的用户思考如何处理异常情况(如果它是可恢复的)时,就使用它们。只是受控异常在Java平台中被过度使用了,这让人们讨厌它们。

以下是我对这个话题的扩展观点。

关于具体问题:

Is the NumberFormatException consider a checked exception? No. NumberFormatException is unchecked (= is subclass of RuntimeException). Why? I don't know. (but there should have been a method isValidInteger(..)) Is RuntimeException an unchecked exception? Yes, exactly. What should I do here? It depends on where this code is and what you want to happen. If it is in the UI layer - catch it and show a warning; if it's in the service layer - don't catch it at all - let it bubble. Just don't swallow the exception. If an exception occurs in most of the cases you should choose one of these: log it and return rethrow it (declare it to be thrown by the method) construct a new exception by passing the current one in constructor Now, couldn't the above code also be a checked exception? I can try to recover the situation like this? Can I? It could've been. But nothing stops you from catching the unchecked exception as well Why do people add class Exception in the throws clause? Most often because people are lazy to consider what to catch and what to rethrow. Throwing Exception is a bad practice and should be avoided.

遗憾的是,没有单一的规则可以让您决定何时捕获、何时重新抛出、何时使用已检查异常和何时使用未检查异常。我同意这会导致很多混乱和很多糟糕的代码。布洛赫阐述了总体原则(你引用了其中的一部分)。一般的原则是将异常重新抛出到可以处理它的层。

需要指出的是,如果在代码中抛出一个受控异常,而catch在上面几层,则需要在您和catch之间的每个方法的签名中声明异常。因此,封装被破坏了,因为抛出路径中的所有函数都必须知道该异常的详细信息。