The following is an excerpt from Rod Johnson's "J2EE design and Developement", which answers a long-standing question and hopes to be useful to everyone.
Exception Handling-checked or unchecked
Java clearly distinguishes two types of exceptions. those that have extended Java. lang. exception is called checked exceptions. The Compiler requires that these exceptions be caught or thrown again. those that have extended Java. lang. runtimeexception exceptions are called unchecked exceptions, which are not required to be captured. of course, you can also capture these exceptions and expand the call stack accordingly, just as you do for checked exceptions. java is the only mainstream language that supports checked exceptions. All C ++ and C # exceptions are equivalent to Java's unchecked exceptions.
First, let's take a look at the behavior when exceptions are received in Java. This is mentioned in the Java tutorial provided by Sun, see the http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html. The advice here is to use checked exceptions in code:
"Because the Java language does not require a method to capture runtime exceptions or define which runtime exceptions are thrown, for programmers, it is tempting to throw only runtime exceptions or inherit all custom exceptions from runtimeexception. these two convenient programming methods allow programmers to write Java code in this way, avoiding the nagging error prompts of the Java compiler, and without defining or capturing any exceptions. this seems convenient, but this deliberate avoidance of Java's requirements for capturing exceptions and defining exception specifications may cause problems for other programmers using your Java class.
Checked exceptions indicates some useful information about an operation. The caller cannot control this operation, but the caller needs to know this information. for example, the file system may be full, the remote connection may be closed, or the access authorization is insufficient to perform this operation.
So what do you get if you throw a runtimeexception or its subclass just because you don't want to define the exception specification? Very simple: you can throw an unspecified exception. Or, this is a way to avoid every exception thrown by a documented method. Is this good? Maybe it is better than simply not documenting the semantics of the method. So the answer is that almost never use unchecked exceptions ."
To sum up, the Orthodox Java practice is to use checked exceptions, while runtimeexception indicates programming errors.
I once agreed with this idea. however, after writing thousands of exception capture code blocks, I come to the conclusion that this theory is not always feasible in practice. I am not the only one who thinks so. since my own point of view is gradually formed at this point, I have noticed that Bruce Eckel is the author of the classic thinking in Java and has changed his point of view. currently, Eckel advocates running exceptions and doubts whether checked exceptions is an unsuccessful test. It should be discarded from Java. see http://www.mindview.net/Etc/Discussions/CheckedExceptions.
Eckel claims observation shows that when a programmer pays attention to a small piece of code, checked exceptions seems to be a pretty idea and can avoid many errors. however, in large-scale code, the opposite is true. for more information, see http://www.octopull.demon.co.uk/java/exceptionaljava.html's "exceptional Java" on Alan Griffin iths.
Using checked exceptions causes the following problems:
1. code expansion. programmers must write code to capture and ignore exceptions that they cannot properly handle, and they will become very discouraged. this is a bad programming practice and experience shows that they happen more frequently than we think. even a good programmer occasionally forgets to correctly nest exceptions, which means that the complete call stack will be lost and the information contained in exceptions will not be so useful.
2. reduced code readability. capture exceptions that cannot be properly handled in the routine and immediately throw them again, making it difficult to find the code that actually does something. the orthodox view of Java holds that this is only a problem for lazy programmers. We should simply ignore this problem. however, this view ignores the facts. for example, the design of the Java core library clearly considers this issue. imagine that if. util. if an iterator interface throws checked exceptions instead of unchecked exceptions, it will be a nightmare to use them. jdo api is another example from Sun's own API, which uses unchecked exceptions. on the contrary, JDBC uses checked exceptions, which is very cumbersome to use.
3. packaging exception endlessly. A checked exceptions must be captured or declared in the exception specification of those methods that may be encountered. this creates an option. You can throw an exception again, or package a low-level exception in a new high-level exception, and then throw it again. if we add some useful information, it is worth packing and throwing an exception again. however, if the original exceptions are unrecoverable, packaging them will be meaningless. if unchecked rollback tions is used, an automatic stack rollback will be triggered in this case, and when checked rollback tions is used, we do nothing more than an equivalent manual stack rollback, in addition, some additional meaningless code must be added to every method in the call stack path to avoid packaging exceptions. this is mainly because I was prompted to rethink my attitude towards exception handling.
4. Fragile prototype declaration. If many code uses an interface, declaring an additional exception specification will cause a lot of code modifications.
5. when defining an interface, checked exceptions does not always work so well. consider the example of full file system in the Java tutorial. if we are talking about a class that uses a file system, there is no problem with this example. what if we are dealing with a class that only promises to store data somewhere (maybe a database? We certainly do not want to harden the coding dependency on Java I/O APIs in this class interface, because this interface may have many different implementations. if checked exceptions is used, we must create a new storage medium-independent exception type for this interface and encapsulate the file system exceptions. whether it is worthwhile to rely on the exception to be recoverable. if it cannot be recovered, we will be useless again.
Many of these problems come down to the following: we caught an unhandled exception and were forced to throw a packaged exception. this is annoying and can easily cause errors (because it is easy to lose the call stack) and is useless. it is better to use unchecked exceptions. unchecked exceptions will trigger automatic stack rollback, and it is also the correct action in the case of a fatal error.
I believe that checked exceptions can be useful in one scenario. This is not like Eckel, but also makes my opinion less orthodox. when an exception is equivalent to another return value of the method, checked exceptions should be used. What's better is that the language will help forcibly check this return value. I just think that the common Java conventions overemphasize this point.
"Checked exceptions is much better than the returned error values in many old languages. programmers will no longer check the returned values of errors sooner or later. It would be great to use the compiler to force correct error handling. such checked exceptions should be part of the API like parameters and return values."
However, I do not recommend using checked exceptions unless the caller can handle them. Checked exceptions should not specifically be used to indicate that some fatal errors have occurred and should not be handled by the caller.
"If the caller code can do something meaningful, use checked exceptions. if the exception is fatal, or the caller cannot capture the exception and gain some benefits, use unchecked exceptions. remember that you can rely on a J2EE container to capture unchecked exceptions and record them."
Here are the guidelines for selecting checked exceptions or unchecked exceptions:
The answer to the question is correct.
----------------------------------------------------
All callers should handle definitions and use checked
Is this a problem? Exception is caused by exceptions.
No, it is only supported during compilation provided by another Java function.
Return values?
----------------------------------------------------
Whether only a few callers have the JDO exception extension runtimeexception.
Need to solve this problem? This allows the caller to capture
Exception, but do not force all calls
All users do this.
----------------------------------------------------
Is there a fatal error? Extended runtimeexception.
Are errors unrecoverable?
----------------------------------------------------
Not clear yet? Extended runtimeexception.
Write all possible exceptions
Enter the document for the caller to determine
Determine whether to capture and capture
Exception
----------------------------------------------------
Make a decision at the package level to determine how each package uses checked and unchecked exceptions. write the unchecked exceptions decision into the document, because many programmers are not used to it. the only danger of using unchecked exceptions is that the document is not properly written. when using unchecked exceptions, you must write all possible exceptions into the document so that the caller can choose whether to capture exceptions. ideally, the compiler should forcibly write all exceptions into javadoc. when allocating resources such as JDBC connections that should be released in all circumstances, whether or not you need to capture exceptions, remember to use a finalize block to ensure correct clearing. remember to use finalize block even if no Catch Block exists.
An uncaptured runtime exception will kill the execution thread, which is sometimes a reason to avoid running exceptions. in some cases, this is a reasonable argument, but this is usually not a problem in J2EE applications, because we seldom control threads, but let the application server do this. the application server will capture and process running exceptions that are not captured in the application code, without suspending the entire Java virtual machine. an uncaptured running exception in the EJB container will cause the EJB container to discard the current EJB instance. if an error is fatal, there is nothing wrong with it.
In the end, using checked exception or unchecked exception is a point of view. it is important not only to write the methods used into the document, but also to respect others' methods. although I tend to use unchecked exception, when maintaining or modifying the code of other programmers who prefer to use only checked exception, I will adopt their methods.
Good practices for Exception Handling
Whether checked exceptions or unchecked exceptions is used, we need to solve the problem of exception nesting. usually this happens when we are forced to capture an exception that we cannot handle, but throw them again. this means we have to wrap the original nested exception in a new exception.
There are some standard exceptions, such as javax. servlet. servletexception provides such packaging functions. among the exceptions of our own applications, we need to define or use a custom exception parent class. These parent classes have a constructor whose original exception is a parameter, the printstacktrace () method is overloaded to display the complete call stack, including the original abnormal call stack. we usually need two such parent classes: checked exceptions and unchecked exceptions. (this is not required in JDK 1.4 because it supports nesting of all exceptions .)
In the example code in this book, the two classes are com. interface21.core. nestedcheckedexception and COM. interface21.core. nestedruntimeexception. in addition. lang. exception and Java. lang. runtimeexception. these two classes are both abstract classes and their subclasses make sense. the definition of nestedruntimeexception is as follows:
Package com. interface21.core;
Import java. Io. printstream;
Import java. Io. printwriter;
Public abstract class nestedruntimeexception extends runtimeexception {
Private throwable rootcause;
Public nestedruntimeexception (string s ){
Super;
}
Public nestedruntimeexception (string S, throwable ex ){
Super;
Rootcause = ex;
}
Public throwable getrootcause (){
Return rootcause;
}
Public String getmessage (){
If (rootcause = NULL ){
Return super. getmessage ();
} Else {
Return super. getmessage () + "; Nested exception is:/n/t" +
Rootcause. tostring ();
}
}
Public void printstacktrace (printstream PS ){
If (rootcause = NULL ){
Super. printstacktrace (PS );
} Else {
PS. println (this );
Rootcause. printstacktrace (PS );
}
}
Public void printstacktrace (printwriter PW ){
If (rootcause = NULL ){
Super. printstacktrace (PW );
} Else {
PW. println (this );
Rootcause. printstacktrace (PW );
}
}
Public void printstacktrace (){
Printstacktrace (system. Err );
}
}
Java 1.4 has introduced welcome improvements in the exception handling field. there is no need to write chained exceptions, and there is no problem with the code that already exists like the above. java. lang. throwable and Java. lang. exception has a new constructor that supports exception nesting and Java. lang. throwable adds the void initcause (throwable t) method so that a root exception can be defined even after the exception is constructed. this method should be called only once when the constructor does not define nested exceptions.
Java 1.4-related exceptions should implement a constructor with nested exceptions as parameters, which then calls new exception constructor. this means that we can always create and throw exceptions in a line of code as follows:
Catch (rootcauseexception ex ){
Throw new myjava14exception ("detailed message", ex );
}
If the exception does not provide such a constructor, we need to use a little more code, like this:
Catch (rootcauseexception ex ){
Myjava13exception Mex = new myjava13exception ("detailed message ");
Mex. initcause (Ex );
Throw Mex;
}
When nested exceptions such as the nestedruntimeexception discussed above are used, remember to follow their own conventions, instead of making a reservation like Java 1.4, so that you can continue to work.
Exceptions in J2EE
When J2EE applications are involved, several special issues need to be considered.
Distributed applications will encounter many checked exceptions. this part should be intentionally done by Sun in the early history of Java, so that remote calls must be explicitly used. all RMI calls, including remote EJB interface calls, throw Java. RMI. remoteException, which makes it impossible to make local and remote calls transparent. this decision is probably correct, because the transparency of local and remote calls is very dangerous, especially for performance. however, this leads to frequent code writing to handle checked exceptions, and these exceptions only mean fatal exceptions that are not worth retrying.
On the servlets and JSP pages, exceptions from the J2EE system level, such as Java. RMI. remoteException is very important to protect interface code. some programmers did not realize this, which led to unfortunate consequences, such as unnecessary dependency on the system framework layer and the opportunity to retry some operations, these operations should have been retried at a lower level. among programmers who recognize these problems, I see two strategies:
1. this exception can be ignored in some parts of the interface. for example, if an exception is caught at a high level such as the parent class of all the classes that process incoming webpage requests, this allows the subclass to throw a class exception in an abstract member function with protected attributes.
2. when an exception is caused by a service logic rather than a remote process call, whether it is checked or unchecked, the client method is used to cancel communication with the remote system and throw an exception. this means that the client method should not simulate the interface of the remote component, and the remote interface always throws Java. RMI. remoteException. this method is called Business Delegate J2EE pattern and is a core J2EE mode.