Java Theory and Practice: an argument about anomalies

Source: Internet
Author: User
Tags error handling file system finally block resource return stack trace tostring access
Most of the recommendations for using exceptions in the Java language suggest that check-type exceptions should be used preferentially in any case where the exception is believed to be captured. Language design (the compiler forces you to list all check-type exceptions that may be thrown in the method signature), as well as early writings on styles and usages, support this recommendation. Recently, several prominent authors have come to believe that unchecked anomalies have a more important place in the design of good Java classes than previously thought. In this article, Brian Goetz examines the pros and cons of using a non-checked type exception.

?? Like C + +, the Java language also provides exceptions for throwing and capturing. However, unlike C + +, the Java language supports both check-and-check-type exceptions. Java classes must declare any check-type exceptions that they throw in the method signature and, for any method, if the method it calls throws a check-type exception with the form E, it must either catch e or also declare it to throw an E (or a parent of e). In this way, the language forces us to document all the expected ways in which we can exit a method.

?? For exceptions caused by programming errors, or exceptions that cannot be expected to be caught by the program (dereference a null pointer, array out of bounds, except 0, and so on), some exceptions are named unchecked exceptions (that is, those inherited from RuntimeException Exception) and does not need to be declared.

?? The traditional view

?? The following excerpt from Sun's "The Java Tutorial" summarizes the traditional idea of declaring an exception to be checked or unchecked (see Resources for more information):

?? Because the Java language does not require methods to capture or specify Run-time exceptions, it is appealing to programmers to write code that throws only Run-time exceptions or that all their exception subclasses inherit from RuntimeException. These programming shortcuts allow programmers to write Java code without interfering with all the critical errors from the compiler, without having to specify or catch any exceptions. While this may seem convenient for programmers, it avoids Java capture or the intent to specify requirements, and can cause problems for programmers who use the classes you provide.

?? A check-type exception represents useful information about a legally specified request, and the caller may have no control over the operation, and the caller needs to be notified about it?? For example, the file system is full, or the connection is closed remotely, or the action is not allowed by access permissions.

?? If you throw a runtimeexception just because you don't want to specify an exception, or if you create a subclass of RuntimeException, what do you have in return? You just get the ability to throw an exception without you specifying to do so. In other words, this is a way to avoid the exceptions that a document method can throw. At what point is this beneficial? In other words, when is it useful to avoid the act of stating a method? The answer is "almost never." ”

?? In other words, Sun tells us that check-type abnormalities should be guidelines. The tutorial continues to explain in a number of ways, usually by throwing exceptions instead of runtimeexception?? Unless you are the JVM.

?? In effective java:programming Language Guide, Josh Bloch provides the following knowledge points about checked and unchecked anomalies, consistent with the recommendations in the "The Java Tutorial" (but not strictly Consistent):

?? 39th: Use exceptions for exception conditions only. That is, do not use exceptions for control flows, such as capturing nosuchelementexception at the time of the call to Iterator.next (), not the first time the Iterator.hasnext () is checked.

?? 40th: Use a check-type exception for recoverable conditions, and use a Run-time exception for programming errors. Here, Bloch responds to the traditional Sun view?? The run-time exception should be used only to indicate programming errors, such as violations of preconditions.

?? 41st: Avoid unnecessary use of check-type exceptions. In other words, do not use a check-type exception for situations where the caller is unlikely to recover from it, or if the only predictable response is that the program exits.

?? 43rd: Throw the exception that fits the abstraction. In other words, an exception thrown by a method should be defined at an abstract level that is consistent with what the method does, and not necessarily in accordance with the underlying implementation details of the method. For example, a method that loads a resource from a file, database, or JNDI should throw some Resourcenotfound exception (usually using an exception chain to hold the implied cause) when the resource cannot be found, rather than the lower IOException, SQLException, or Namingexception.

?? Re-examining the orthodox view of non-censorship anomalies

?? Recently, several respected experts, including Bruce Eckel and Rod Johnson, have publicly stated that although they initially fully agreed with the orthodox view of censorship anomalies, they have decided that the idea of exclusive use of check-type anomalies is not as good as it initially appears, and for many large projects, Check-type exceptions have become an important source of problem. Eckel put forward a more extreme view, suggesting that all anomalies should be unchecked; Johnson's view should be conservative, but it still implies that traditional preference-checking abnormalities are excessive. (It is worth mentioning that the designer of C # chose to ignore the check-type exception in the language design so that all exceptions are not checked, so they are almost certainly rich in Java technology experience.) But then they did leave room for the implementation of the check-type exception. )

?? Some criticisms of check-type anomalies

?? Eckel and Johnson all pointed out a similar list of questions about check-type anomalies, some of the intrinsic properties of the check-type exception, some of the properties of the checked exception's specific implementations in the Java language, and some just simple observations, It is mainly about how extensive error usage of check-type anomalies becomes a serious problem, which may cause the mechanism to be reconsidered.

?? Check-type exception inappropriately exposes implementation details

?? How many times have you seen (or written) a method that throws SQLException or IOException, even if it doesn't seem to have anything to do with a database or a file? It is common for developers to summarize all the exceptions that might be thrown in the initial implementation of a method and add them to the throws clause of the method (many Ides even help you perform the task). One of the problems with this direct approach is that it violates the 43rd article of the Bloch. The level of abstraction at which the thrown exception is located is inconsistent with the method in which it is thrown.

?? A method for loading user profiles that should throw nosuchuserexception when no user is found, instead of SQLException?? The caller can well anticipate that the user may not be able to find it, but does not know how to handle SQLException. The exception chain can be used to throw a more appropriate exception without discarding the details about the underlying failure (such as stack traces), allowing the abstraction layer to isolate the hierarchies on top of them from the details of the hierarchies that are located beneath them, while retaining information that might be useful for debugging.

?? It is said that the design of such a JDBC package takes such a way that it is difficult to avoid the problem. Each method in the JDBC interface throws SQLException, but there may be many different types of problems that can go through the process of accessing a database, and different methods may be susceptible to different error patterns. A SQLException may indicate a system-level problem (cannot connect to a database), a logical problem (no more rows in the result set), or a problem with a specific data (the primary key you just tried to insert into the row already exists or violates entity integrity constraints). It is impossible for callers to distinguish between these different types of SQLException without an unforgivable attempt to parse the fault of the message body. (SQLException does support methods for getting database-specific error codes and SQL state variables, but in practice these are rarely used to differentiate between different database error conditions.) )

?? Unstable method signature

?? Unstable method signature problem is related to the previous problem?? If you just pass an exception through one method, you have to change its method signature each time the implementation of the method is changed, and change all the code that invokes the method. Once a class has been deployed into a product, managing these fragile method signatures becomes an expensive task. The problem, however, is essentially not following another symptom of the 43rd article proposed by Bloch. method should throw an exception when it encounters a failure, but the exception should reflect what the method does, not how it does it.

?? Sometimes, when programmers are bored with adding or removing exceptions from method signatures because of changes in implementation, they are not using an abstraction to define the types of exceptions that a particular hierarchy might throw, but simply declare all their methods as throwing Exception. In other words, they've decided that anomalies are just causing trouble and basically shutting them down. Needless to say, this approach is usually not a good error-handling strategy for most of the code that can be used arbitrarily.

?? Difficult to understand code

?? Because many methods throw a number of different exceptions, the error-handling code is likely to be higher relative to the actual functional code, making it difficult to find the code that actually completes the function in a method. Exceptions are intended to reduce code by centralizing error handling, but a method with three lines of code and six catch blocks (where each block simply logs an exception or wraps and throws an exception) looks bloated and makes the simple code obscure.

?? Unusually submerged

?? We've all seen code that captures an exception, but there's no code in the catch block. Although this programming practice is obviously bad, it's easy to see how it happens?? During the prototyping, someone wraps the code through the Try...catch block, and then forgets to return and populate the Catch block. Although this error is common, this is also one of the better tools that can help us. For places that are flooded, it is easy to detect and issue a warning through an editor, compiler, or static check tool.

?? The extremely common Try...catch block is another form of exception drowning and is more difficult to detect because it is the structure of the exception class hierarchy in the Java class library (suspicious). Let's assume that a method throws four different types of exceptions, and the caller encounters any of them that will catch, record them, and return. One way to implement this policy is to use a try...catch block with four catch clauses, one for each exception type. To avoid problems that the code cannot understand, some developers will refactor the code, as shown in Listing 1:

Listing 1. Accidentally submerged RuntimeException

try {
DoSomething ();
}
catch (Exception e) {
Log (e);
}

?? Although the code is more compact than four catch blocks, does it have a problem?? It also captures any runtimeexception that may be thrown by dosomething and prevents them from spreading.

?? Excessive exception wrapping

?? If the exception is generated in an underlying facility and spreads up through many layers of code, it may be captured, wrapped, and thrown back several times before it is finally processed. When the exception is finally recorded, the stack trace may have many pages, because the stack trace may be replicated multiple times, each of which is once in the wrapper layer. (in JDK 1.4 and later versions, the implementation of the exception chain mitigated the problem to some extent.) )

?? Method of substitution

?? The author of Bruce eckel,thinking in Java (see Resources) claims that after years of using the Java language, he has come to the conclusion that a check-type exception is an error?? An experiment that should be declared a failure. Eckel advocates the use of all exceptions as non-checked, and provide the class in Listing 2 as a way to turn a check exception into an unchecked exception, while preserving the ability to catch a particular type of exception when an exception is spread up from the stack (for an explanation of how to use this method, see his reference Article in the section):

Listing 2. Eckel Exception Adapter Class

Class Exceptionadapter extends RuntimeException {
Private final String StackTrace;
Public Exception originalexception;
Public Exceptionadapter (Exception e) {
Super (E.tostring ());
Originalexception = e;
StringWriter SW = new StringWriter ();
E.printstacktrace (new PrintWriter (SW));
StackTrace = Sw.tostring ();
}
public void Printstacktrace () {
Printstacktrace (System.err);
}
public void Printstacktrace (Java.io.PrintStream s) {
Synchronized (s) {
S.print (GetClass (). GetName () + ":");
S.print (StackTrace);
}
}
public void Printstacktrace (Java.io.PrintWriter s) {
Synchronized (s) {
S.print (GetClass (). GetName () + ":");
S.print (StackTrace);
}
}
public void Rethrow () {throw originalexception;}
}

?? If you look at the discussions on the Eckel Web site, you will find that the respondents are severely split. Some people think his proposal is absurd; some people think it is an important idea. (My point is that, while it's really hard to use exceptions properly, and there's a lot of bad examples, but most people who agree with him do it for the wrong reasons, and that's similar to the fact that a politician who sits on a platform that can get a chocolate-free access to a large turnout of 10-year-old children. )

?? Rod Johnson is the author of the Java EE Design and Development (see Resources), which is one of the best books I've read on the aspects of java-based development, EE, and so on. He took a less radical approach. He enumerates multiple categories of exceptions and determines a policy for each category. Some exceptions are essentially secondary return codes (which usually indicate a violation of business rules), while some exceptions are variants of "some terrible error occurred," such as a database connection failure. Johnson advocates the use of a check-type exception for the exception (optional return code) for the first category, and a Run-time exception for the latter. In the category of "something terrible wrong", the motivation is simply to recognize that no caller can handle the exception effectively, so it may also be able to spread up the stack in various ways and minimize the impact of the intermediate code (and minimize the likelihood of an exception drowning).

?? Johnson also cites an intermediate case in which he raises a question, "Is it only a small number of callers who wish to deal with the problem?" "For these cases, he also recommends the use of a non-checked type exception." As an example of this category, did he enumerate the JDO exceptions?? In most cases, the JDO exception represents a situation that the caller does not want to handle, but in some cases it is useful to catch and handle a particular type of exception. Instead of letting the rest of the JDO classes compensate for this possibility by capturing and then throwing back the exceptions, he recommends using unchecked exceptions here.

?? Using a non-checked type exception

?? The decision about whether to use an unchecked exception is complex, and obviously there is no obvious answer. Sun's advice is to use them for any situation, and the C # method (that is, Eckel and others agree) is not used for anything. Other people say, "There is a middle case." ”

?? By using exceptions in C + + where all of the exceptions are checked out, I've found that one of the biggest risks of a non-checked exception is that it's not documented in the way that the checked exception was used. Unless the creator of the API explicitly documents the exception that will be thrown, the caller has no way of knowing what the exception will be caught in their code. Unfortunately, my experience is that most C + + APIs are poorly documented, and even a well documented API lacks enough information about the exceptions that might be thrown from a given method. I don't see any reason to say that the problem is not as common as the Java class library because the Jav class library relies heavily on unchecked exceptions. Relying on your own or your partner's programming skills is very difficult; if you have to rely on a person's documentation skills, it would be scary for his code to use 16 frames from the call stack as your primary error-handling mechanism.

?? Documentation issues further emphasize why laziness is a bad reason for choosing to use a non-checked type exception. Because of the burden of adding to the package for documentation, the use of a non-checked exception should be even higher than using a check-type exception (when documenting the unchecked exception that you throw is more important than a check-type exception).

?? Document, document, document

?? If you decide to use an unchecked exception, you need to document the selection thoroughly, including all the unchecked exceptions that a method might throw in Javadoc. Johnson recommends selecting both check-and-check-type exceptions on a per-package basis. When using a non-checked exception, remember that even if you do not catch any exceptions, you may need to use a try...finally block, which allows you to perform cleanup actions such as closing a database connection. For check-type exceptions, we have try...catch used to prompt for the addition of a finally clause. We do not have this support to be able to rely on non checked type exceptions.



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.