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

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


当前回答

关于未检查异常和已检查异常之间的区别,我最喜欢的描述来自Java教程的试用文章“未检查异常-争议”(很抱歉在这篇文章中介绍了所有基本的内容-但是,嘿,基本的有时是最好的):

这是底线原则:如果客户可以合理地 希望从异常中恢复,使其成为受控异常。如果 客户端不能做任何事情来从异常中恢复 未经检查的异常

“抛出哪种类型的异常”的核心是语义的(在某种程度上),上面的引用提供了一个很好的指导方针(因此,我仍然被c#摆脱受控异常的概念所震撼——特别是Liskov认为它们有用)。

接下来的问题就变得合乎逻辑了:编译器希望我显式地响应哪些异常?你希望客户能从中恢复过来。

其他回答

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

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

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

许多人说检查异常(即你应该显式地捕获或重新抛出的异常)根本不应该使用。例如,它们在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.

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

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

小薇。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)

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

关于未检查异常和已检查异常之间的区别,我最喜欢的描述来自Java教程的试用文章“未检查异常-争议”(很抱歉在这篇文章中介绍了所有基本的内容-但是,嘿,基本的有时是最好的):

这是底线原则:如果客户可以合理地 希望从异常中恢复,使其成为受控异常。如果 客户端不能做任何事情来从异常中恢复 未经检查的异常

“抛出哪种类型的异常”的核心是语义的(在某种程度上),上面的引用提供了一个很好的指导方针(因此,我仍然被c#摆脱受控异常的概念所震撼——特别是Liskov认为它们有用)。

接下来的问题就变得合乎逻辑了:编译器希望我显式地响应哪些异常?你希望客户能从中恢复过来。

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