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

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


当前回答

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

For example let say you have some client-server application and client had made a request for some resource that couldn't be find out or for something else error some might have occurred at the server side while processing the user request then it is the duty of the server to tell the client why he couldn't get the thing he requested for,so to achieve that at server side, code is written to throw the exception using throw keyword instead of swallowing or handling it.if server handles it/swallow it, then there will be no chance of intimating to the client that what error had occurred.

注意:为了清楚地描述发生的错误类型,我们可以创建自己的Exception对象并将其抛出给客户端。

其他回答

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

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

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

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

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

上述异常是否被认为是受控异常? 没有 如果异常是RuntimeException,那么您正在处理的异常并不会使其成为Checked exception。 RuntimeException是未检查的异常吗? 是的

受控异常是java.lang.Exception的子类 未检查异常是java.lang.RuntimeException的子类

抛出已检查异常的调用需要包含在try{}块中,或者在方法调用方的更高级别中处理。在这种情况下,当前方法必须声明它抛出上述异常,以便调用者可以做出适当的安排来处理异常。

希望这能有所帮助。

问:我应该把确切的泡沫 异常或屏蔽它使用异常?

A:是的,这是一个非常好的问题,也是重要的设计考虑因素。Exception类是一个非常通用的异常类,可用于包装内部低级异常。您最好创建一个自定义异常,并将其封装在其中。但是,还有一个很大的问题——永远不要模糊潜在的根本原因。对于前任,不要做下面的事情

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException("Cannot login!!"); //<-- Eat away original root cause, thus obscuring underlying problem.
}

你可以这样做:

try {
     attemptLogin(userCredentials);
} catch (SQLException sqle) {
     throw new LoginFailureException(sqle); //<-- Wrap original exception to pass on root cause upstairs!.
}

对生产支持团队来说,消除原始的根本原因,掩盖无法恢复的实际原因是一场噩梦,因为他们只能访问应用程序日志和错误消息。 虽然后者是一种更好的设计,但许多人不经常使用它,因为开发人员无法将底层消息传递给调用者。因此,请明确指出:无论是否封装在任何特定于应用程序的异常中,始终将实际异常传递回去。

在尝试捕获runtimeexception时

runtimeexception作为一般规则不应该被尝试捕获。它们通常是一个编程错误的信号,应该被置之不理。相反,程序员应该在调用一些可能导致RuntimeException的代码之前检查错误条件。为例:

try {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welcome to my site!);
} catch (NullPointerException npe) {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

这是一种糟糕的编程实践。相反,null检查应该像-那样执行

if (userObject != null) {
    setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} else {
   sendError("Sorry, your userObject was null. Please contact customer care.");
}

但有时这种错误检查是昂贵的,例如数字格式,考虑这个-

try {
    String userAge = (String)request.getParameter("age");
    userObject.setAge(Integer.parseInt(strUserAge));
} catch (NumberFormatException npe) {
   sendError("Sorry, Age is supposed to be an Integer. Please try again.");
}

在这里,预调用错误检查不值得花费精力,因为它本质上意味着复制parseInt()方法中的所有字符串到整数转换代码——如果由开发人员实现,则很容易出错。因此,最好是取消try-catch。

因此NullPointerException和NumberFormatException都是runtimeexception,捕获一个NullPointerException应该替换为一个优雅的空检查,而我建议显式捕获NumberFormatException以避免可能引入容易出错的代码。

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

For example let say you have some client-server application and client had made a request for some resource that couldn't be find out or for something else error some might have occurred at the server side while processing the user request then it is the duty of the server to tell the client why he couldn't get the thing he requested for,so to achieve that at server side, code is written to throw the exception using throw keyword instead of swallowing or handling it.if server handles it/swallow it, then there will be no chance of intimating to the client that what error had occurred.

注意:为了清楚地描述发生的错误类型,我们可以创建自己的Exception对象并将其抛出给客户端。

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,但不需要这样做,事实上,实现不需要维护抛出的相同的未检查异常,因为这些异常不是契约的一部分。