Three principles for Java to effectively handle exceptions _java

Source: Internet
Author: User
Tags exception handling stack trace throwable

The reason why an exception is a powerful debugging tool is that it answers the following three questions:

1, what went wrong?

2, where is the fault?

3, why the error?

In cases where an exception is used effectively, the exception type answers "What" is thrown, and the exception stack trace answers "where" is thrown, and the exception message answers "Why" is thrown, and if your exception does not answer all of the above questions, then you may not be able to use them well.

There are three principles that can help you maximize the use of exceptions during debugging, and these three principles are:

1, specific and clear

2, early throw

3. Delayed capture

In order to illustrate the three principles of effective exception handling, this paper discusses the jcheckbook of personal financial Manager class, which is used to record and track bank account activities such as access payments and Bill issuing Jcheckbook.

Concrete Clear

Java defines the hierarchy of an exception class, which begins with Throwable, expands error and exception, and exception expands runtimeexception. As shown in Figure 1.

These four classes are generalized and do not provide much error information, although instantiating these classes is syntactically valid (e.g., new Throwable ()), but it is best to look at them as virtual base classes and use their more specific subclasses. 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 package defines a subclass of the exception class IOException, which is more specific to FileNotFoundException, Eofexception and Objectstreamexception these ioexception subclasses. Each describes a specific type of I/O error: File loss, the end of the exception file, and the wrong serialized object stream. The more specific the exception, the better our program can answer the question "What's wrong".

It is also important to be as clear as possible when catching exceptions. For example, Jcheckbook can handle filenotfoundexception by asking for a user's filename again, and for eofexception, it can continue to run according to the information read before the exception is thrown. If the 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 more than one catch block for the same try block to properly handle each exception individually.

File Prefsfile = new file (prefsfilename);
 
try{
  readpreferences (prefsfile);
}
catch (FileNotFoundException e) {
  //alert the user this specified file
  //does not exist
}
catch (Eofe Xception e) {
  //alert the user this end of the file
  //is reached
}
catch (Objectstreamexception E {
   //alert the user that ' the ' file is corrupted
}
catch (IOException e) {
  //alert the user that some O ther i
  /O/error occurred
}

Jcheckbook provides users with a clear message that catches exceptions 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 brought by 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 to the user.

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 IOException is thrown. In this way, the program can provide specific information as much as possible, but it is also capable of handling unforeseen other anomalies.

Sometimes a developer captures a generic exception and displays the exception class name or print stack information for "concrete". Don't do this! Users who see java.io.EOFException or stack information can only get headaches rather than getting help. Specific exceptions should be caught and the user is prompted with the exact information in "words". However, the exception stack can be printed in your log file. Remember, exceptions and stack information are used to help developers rather than users.

Finally, it should be noted that Jcheckbook does not readPreferences() catch exceptions in, but instead leaves the capture and handling exceptions to the user interface layer, so that the user can be notified by dialog boxes or otherwise. This is referred to as "deferred capture", as discussed below.

Throw early

The exception stack information provides an exact sequence of method call chains that cause an exception to occur, including the class name, method name, code file name, or even number of rows in each method invocation to pinpoint the scene where the exception appears.

Java.lang.NullPointerException at
Java.io.FileInputStream.open (Native method) at
Java.io.FileInputStream. <init> (fileinputstream.java:103) at
Jcheckbook. Jcheckbook.readpreferences (jcheckbook.java:225) at
Jcheckbook. Jcheckbook.startup (jcheckbook.java:116) at
Jcheckbook. Jcheckbook.<init> (jcheckbook.java:27) at
Jcheckbook. Jcheckbook.main (jcheckbook.java:318)

The above shows the case where the open () method of the FileInputStream class throws NullPointerException. But note that it FileInputStream.close() is part of the standard Java class Library, and it is likely that the problem with this exception lies in our code itself rather than the Java API. So the problem is likely to appear in one of the previous methods, but luckily it's also printed on the stack.

Unfortunately, NullPointerException is the least informative (and most often encountered, and crashes) exception in Java. It does not mention the things we care about most: where is null. So we had to take a few steps back and find out what went wrong.

By stepping back the trace stack information and examining the code, we can determine that the reason for the error is to readPreferences() pass in an empty filename parameter. Now that readPreferences() you know that it cannot handle empty file names, check the condition immediately:

public void readpreferences (String filename)
throws illegalargumentexception{
  if (filename = = null) {
     throw new IllegalArgumentException ("filename is null");
  } If
 
  //...perform other operations
 
  ... InputStream in = new FileInputStream (filename);
 
  ... read the preferences file ...
}

By throwing an exception early (also known as "rapid Failure"), the exception is clear and accurate. The stack information immediately reflects what went wrong (provided an illegal parameter value), why it was wrong (the filename cannot be null), and where the error occurred ( readPreferences() the previous part). So that our stack of information can be faithfully provided:

Java.lang.IllegalArgumentException:filename is null at
Jcheckbook. Jcheckbook.readpreferences (jcheckbook.java:207) at
Jcheckbook. Jcheckbook.startup (jcheckbook.java:116) at
Jcheckbook. Jcheckbook.<init> (jcheckbook.java:27) at
Jcheckbook. Jcheckbook.main (jcheckbook.java:318)

In addition, the exception information contained ("File name is empty") makes the information more informative by explicitly answering what is empty, and this answer is not available to the nullpointerexception thrown in our previous code.

By throwing an exception immediately when an error is detected, you can effectively avoid unnecessary object construction or resource occupancy, such as a file or network connection. Similarly, the cleanup that comes with opening these resources can be dispensed with.

Deferred capture

One of the mistakes that rookie and master can make is to catch a program before it can handle an exception. The Java compiler indirectly encourages this behavior by requiring that the detected exception be caught or thrown. It is natural to wrap the code in a try block immediately and use catch to catch the exception so that the compiler does not complain.

The question is, what happens when you catch the exception? The last thing you should do is to do nothing. An empty catch block is equal to dropping the entire exception into a black hole, and it can show that all information about when and where to go wrong is lost forever. It's a little bit better to write the exception in the log, at least for the record. But we can't always expect users to read or understand log files and exception information. It is also inappropriate to readPreferences() display an 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 the error dialog box is obviously not a choice. At the same time, regardless of HTML or C/S version, configuration information is read on the server, and error messages need to be displayed to the Web browser or client program. readPreferences()These future needs should also be taken into account at design time. Proper separation of user interface code and program logic can improve the reusability of our code.

Capturing it prematurely before the conditional handling of an exception usually results in more serious errors and other exceptions. For example, if the previous readPreferences() method captures and records the filenotfoundexception that might be thrown immediately when the FileInputStream construct method is invoked, the code becomes the following:

public void readpreferences (String filename) {
  //...
 
  InputStream in = null;
 
  DO does this!!!
try{in
  = new FileInputStream (filename);
}
catch (FileNotFoundException e) {
  logger.log (e);
}
 
In.read (...);
 
//...
}

The above code captures it without the ability to recover from the filenotfoundexception at all. If the file cannot be found, the following method obviously cannot read it. What happens if Readpreferences () is asked to read a nonexistent file? Of course, FileNotFoundException will be recorded, if we go to the log file, we will know. However, what happens when a 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 back of the log information. It's going to be nullpointerexception, and it's very annoying that this anomaly is very specific. The error message not only misled us about what went wrong (the real mistake was filenotfoundexception rather than nullpointerexception), but also misled the wrong source. The real problem lies in the number of rows that are thrown at the nullpointerexception, and there is a possibility that several methods are invoked and classes are destroyed. Our attention was attracted by this little fish from the real mistake, until we looked back at the log to find out the source of the problem.

Since the readPreferences() real thing is not to catch these anomalies, what should it be? It seems counterintuitive, and usually the most appropriate thing to do is to do nothing and not catch the exception immediately. Give the caller the responsibility to readPreferences() study the proper way to deal with the missing configuration file, it might prompt the user to specify another file, or use the default value, perhaps warning the user and exiting the program.

The way to transfer the responsibility of exception handling to the upstream of the call chain is to declare an exception in the throws clause of the method. When declaring an exception that may be thrown, it is better to notice the more specific. This is used to identify the type of exception that the program calling your method needs to know and prepare to handle. For example, the "Delay capture" version readPreferences() might be like this:

public void readpreferences (String filename)
throws IllegalArgumentException,
FileNotFoundException, ioexception{
  if (filename = = null) {
      throw new illegalargumentexception ("filename is null");
   }//if
 
   // ...
 
   InputStream in = new FileInputStream (filename);
 
//...
}

Technically, the only exception we need to declare is IOException, but we explicitly declare that the method might throw a filenotfoundexception. IllegalArgumentException is not necessarily declared because it is a non-checked exception (that is, a subclass of RuntimeException). However, it is stated to document our code (these exceptions should also be annotated in the Javadocs of the method).

Of course, eventually your program needs to catch an exception, or it will terminate unexpectedly. But the trick here is to catch exceptions at the right level so that your program can either recover meaningfully from the exception and continue without causing a deeper error, or be able to provide users with clear information, including guiding them to recover from the error. If your method is not competent, do not handle the exception, leave it behind to capture and handle at the right level.

Summarize

As experienced developers know, the biggest difficulty with debugging programs is not to fix bugs, but to find hidden hiding places from massive amounts of code. Just follow the three principles of this article to help you track and eliminate bugs, make your programs more robust, and be more user-friendly. The above is the entire content of this article, I hope to be able to study or work to bring certain help.

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.