Exceptions in Java provide a consistent mechanism for identifying and responding to error situations, and effective exception handling can make programs more robust and easy to debug. An anomaly is a powerful debugging tool that answers the following three questions: What went wrong? Where is the error? In the case of a valid use exception, the exception type answers "What" is thrown, the exception stack trace answers "where" thrown, the exception information answered "Why" will throw, If your exception does not answer all of the above questions, then you may not be using them well. There are three principles that can help you to maximize the use of exceptions during debugging, and the three principles are: specific explicit early-throw delay capture in order to illustrate the three principles of effective exception handling, this paper discusses the jcheckbook of personal financial Manager class. Jcheckbook is used to record and track bank account activities such as access and billing.
Concrete and clearJava defines the hierarchy of an exception class, starting with Throwable, extending the error and exception, And exception extends out of Runtimeexception.1. These four classes are generalized and do not provide much error information, although instantiating these classes is syntactically legal (such as New Throwable ()), but it is best to see them as virtual base classes, Subclasses that use them more specific. Java has provided a large number of exception subclasses, and you can define your own exception classes if you want to be more specific. For example: The Java.io package defines the subclass IOException of the exception class, which is more specific filenotfoundexception, Eofexception and objectstreamexception of these ioexception subclasses. Each describes a specific type of I/O error: The file is missing, the exception file ends, and the wrong serialized object stream. The more specific the exception, the better our program can answer the question of what went wrong. It is also important to try to be clear when catching exceptions. For example: Jcheckbook can process filenotfoundexception by re-asking the user's file name, and for Eofexception, it can continue to run based on the information read before the exception is thrown. If Objectstreamexception is thrown, the program should prompt the user that the file is corrupted and should use a backup file or other file. Java makes it easy to catch exceptions explicitly, because we can define multiple catch blocks on the same try block, so that each exception is handled appropriately. Jcheckbook provides the user with explicit information to catch an exception by using multiple catch blocks. For example, if FileNotFoundException is captured, it can prompt the user to specify another file, and in some cases the extra coding effort from multiple catch blocks may be an unnecessary burden, but in this case, The extra code does help the program provide a more user-friendly response. In addition to the exceptions handled by the first three catch blocks, the last catch block provides a more generalized error message to the user when the IOException is thrown. In this way, the program can provide specific information as much as possible, but it also has the ability to handle unexpected exceptions. Sometimes the developer catches the fan exception and displays the exception class name or prints the stack information for "concrete". Don't do this! Users who see java.io.EOFException or stack information only have headaches rather than getting help. You should catch specific exceptions and use "people" to prompt the user for the exact information. However, the exception stack can bePrint in the log file. Remember that exceptions and stack information are used to help developers, not users. Finally, it should be noted that Jcheckbook does not catch an exception in Readpreferences (), but instead leaves the capture and handling exception to the user interface layer, which allows the user to be notified by dialog boxes or other means. This is called "delayed capture" and is discussed below.
Early ThrowThe exception stack information provides an exact sequence of method call chains that cause exceptions, including the class name, method name, code file name, and even number of rows for each method call to pinpoint the scene where the exception occurred. The above shows the case where the open () method of the FileInputStream class throws NullPointerException. Note that Fileinputstream.close () is part of the standard Java class Library, and it is likely that the problem with this exception is that our code itself is not the Java API. So the question is likely to appear in one of the previous methods, fortunately it is also printed in the stack information. Unfortunately, NullPointerException is the least amount of information in Java (but also the most often encountered and crashes) exception. It doesn't even mention what we care about the most: where is null. So we had to go back a few steps to find out what went wrong. By stepping back the trace stack information and examining the code, we can determine that the error was due to an empty file name parameter passed to Readpreferences (). Now that readpreferences () knows it can't handle the empty file name, check the condition immediately: by throwing an exception early (also known as "rapid Failure"), the exception is clear and accurate. The stack information immediately reflects what went wrong (providing an illegal parameter value), why the error occurred (the file name cannot be a null value), and what was wrong (the first part of Readpreferences ()). This allows our stack information to be provided truthfully: In addition, the exception information contained in it ("file name is empty") by explicitly answering what is empty this problem makes the information provided by the exception richer, and this answer is not available from the nullpointerexception that we have thrown in our previous code. Rapid failure by throwing an exception immediately when an error is detected can effectively avoid unnecessary object construction or resource consumption, such as a file or network connection. Also, the cleanup operations that open up these resources can be avoided.
Delayed CaptureOne of the mistakes that rookie and master can make is to capture a program before it has the ability to handle it. The Java compiler indirectly encourages this behavior by requiring that the detected exception be caught or thrown. It's a natural practice to wrap the code in a try block immediately, and catch the exception using catches to prevent the compiler from getting an error. The question is, what happens when you catch an exception after the capture? The last thing to do is to do nothing. An empty catch block is tantamount to throwing an entire exception into a black hole, and all the information that explains when and why the error occurred is lost forever. Writing the exception to the log is a little bit better, at least there are records to check. But we can't always expect users to read or understand log files and exception information. It is also inappropriate to have readpreferences () display the Error message dialog box, because although Jcheckbook is currently a desktop application, we plan to turn it into an HTML-based Web application. In that case, displaying an error dialog box is obviously not a choice. At the same time, regardless of the HTML or C/S version, the configuration information is read on the server, and the error message needs to be displayed to the Web browser or client program. Readpreferences () should also take these future requirements into account at design time. Proper separation of user interface code and program logic can improve the reusability of our code. Catching it prematurely before conditional handling of the exception usually results in more serious errors and other exceptions. For example, if the Readpreferences () method above captures and records the filenotfoundexception that might be thrown as soon as the FileInputStream construction method is called, the code becomes the following: The code of the polygon captures it when it is completely incapable of recovering from the filenotfoundexception. If the file cannot be found, the following method obviously cannot read it. What happens if Readpreferences () is asked to read files that do not exist? Of course, FileNotFoundException will be recorded, if we were to read the log file, we will know. But what happens when the program tries to read data from a file? Since the file does not exist, the variable in is empty, and a nullpointerexception is thrown. When debugging a program, instinct tells us to look at the information at the back of the log. It's going to be nullpointerexception, and it's really annoying that this anomaly is very not specific. Error messages not only mislead us about what went wrong (the real error is filenotfoundexception rather than nullpointerexception), but it also misleads the wrong source. The real problem is the number of rows thrown nullpointerexception, between which there isThere may be several calls to methods and the destruction of classes. Our attention was drawn from the real error by this little fish, until we looked back at the log to find the source of the problem. Since what readpreferences () really should do is not catch these anomalies, what should it be? It seems counterintuitive, and usually the best thing to do is to do nothing and not catch the anomaly right away. Give responsibility to the caller of readpreferences () and let it investigate the appropriate method of handling the missing profile, which may prompt the user to specify a different file, or use the default value, and perhaps warn the user and exit the program. The way to pass the responsibility of exception handling toward the upstream of the call chain is to declare the exception in the throws clause of the method. When declaring an exception that may be thrown, the more specific the attention, the better. This is used to identify the type of exception that the program calling your method needs to know and is ready to handle. For example, the "delayed capture" version of Readpreferences () might be: Technically, the only exception we need to declare is IOException, but we explicitly state that the method might throw filenotfoundexception. IllegalArgumentException is not mandatory because it is a non-inspection exception (that is, RuntimeException subclass). However, declaring it is to document our code (these exceptions should also be noted in the Javadocs of the method). Of course, your program eventually needs to catch an exception, or it will terminate unexpectedly. But the trick here is to catch the exception at the right level so that your program can either recover meaningfully from the exception and continue without causing a deeper error, or provide the user with clear information, including directing them to recover from the error. If your method is not competent, then do not handle the exception, leave it behind to capture and deal with it at the right level.
Conclusion
Experienced developers know that the biggest difficulty in debugging is not fixing bugs, but finding a place to hide from the vast code. By following the three principles of this article, you will be able to help you track and eliminate defects, make your programs more robust, and more user-friendly.
Three principles for effectively handling Java exceptions