A detailed analysis of the three principles of handling Java exceptions

Exceptions in Java provide a consistent mechanism for identifying and responding to error conditions. Effective exception handling makes programs more robust and easier to debug.

The exception is that a powerful debugging method is that it answers the following three questions:

What went wrong?

Where is the mistake?

Why is it wrong?

In the case of effective use exceptions, the exception type replies "what" is thrown, the exception stack trace answers "Where" is thrown, the exception message answers "Why" will be thrown, if your exception does not answer all of the above The problem, then maybe you are not using them well.

There are three principles that can help you get the most out of your exceptions during debugging. These three principles are:

Specifically

Throw early

Delayed capture

In order to elaborate on these three principles of effective exception handling, this article is discussed through the creation of the personal financial manager class JCheckbook, which is used to record and track bank account activities such as deposits and withdrawals and ticket issuance.

Specifically

Java defines a hierarchy of exception classes, starting with Throwable, extending Error and Exception, and Exception extends RuntimeException as shown in Figure 1.

Figure 1. Java exception hierarchy

These four classes are generalized and do not provide much error information. Although instantiating these classes is syntactically legal (eg new Throwable()), it is best to treat them as virtual base classes. They are more specialized subclasses. Java has provided a large number of exception subclasses. If you need to be more specific, you can also define your own exception classes.

For example, the java.io package package defines a subclass IOException of the Exception class, and more specialized subclasses of IOException such as FileNotFoundException, EOFException, and ObjectStreamException.

Each describes a specific type of I/O error: file loss, exception file end, and incorrect serialized object stream. The more specific the exception, the better our program can answer the question "What went wrong."

It is also important to be as clear and important as possible when capturing anomalies.

For example, JCheckbook can handle FileNotFoundException by re-query the user's file name. For EOFException, it can continue to run based on the information read before the exception is thrown.

If an ObjectStreamException is thrown, the program should prompt the user that the file is corrupt and should use a backup file or other file.

Java makes it easy to explicitly catch exceptions, because we can define multiple catch blocks for the same try block, so that each exception is handled appropriately.

File prefsFile = new File(prefsFilename);

Try{

readPreferences(prefsFile);

}

Catch (FileNotFoundException e){

// alert the user that the specified file

// does not exist

}

Catch (EOFException e){

// alert the user that the end of the file

// was reached

}

Catch (ObjectStreamException e){

// alert the user that the file is corrupted

}

Catch (IOException e){

// alert the user that some other I/O

// error occurred

}

JCheckbook provides users with clear information about catching exceptions by using multiple catch blocks.

For example: if a FileNotFoundException is caught, it can prompt the user to specify another file. In some cases, the extra encoding effort caused by multiple catch blocks may be an unnecessary burden, but in this case, the extra code does help. The program provides a more user-friendly response.

In addition to the exceptions handled by the first three catch blocks, the last catch block gives the user a more general error message when the IOException is thrown. This way, the program can provide as much information as possible, but also has the ability to handle it. Other anomalies that were unexpected.

Sometimes developers catch normalized exceptions and display exception class names or print stack information for "specific".

Don't do this!

Users seeing java.io.EOFException or stack information only have a headache instead of getting help. Specific exceptions should be captured and the user should be prompted with the exact information. However, the exception stack can be printed in your 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 exceptions in readPreferences(), but instead leaves the capture and processing exceptions to the user interface layer so that users can be notified by dialog or other means. This is called "delayed capture" and will be discussed below.

Throw early

The exception stack information provides the exact order of the method call chain that caused the exception to occur, including the class name, method name, code file name, and even the number of rows for each method call, to pinpoint the scene where the exception occurred.

java.lang.NullPointerException

At java.io.FileInputStream.open(Native Method)

At java.io.FileInputStream. (FileInputStream.java:103)

At jcheckbook.JCheckbook.readPreferences(JCheckbook.java:225)

At jcheckbook.JCheckbook.startup(JCheckbook.java:116)

At jcheckbook.JCheckbook. (JCheckbook.java: 27)

At jcheckbook.JCheckbook.main(JCheckbook.java:318)

The above shows the case where the open() method of the FileInputStream class throws a NullPointerException.

Note, however, that FileInputStream.close() is part of the standard Java class library, and the most likely cause of this exception is our code itself, not the Java API. So the problem is likely to appear in one of the previous methods, but fortunately it is also printed in the stack information.

Unfortunately, NullPointerException is the least informative (but most frequently encountered and crashing) exception in Java. It doesn't mention what we care most about: where is null. So we have to go back a few steps to find out what went wrong.

By stepping back through the trace stack information and checking the code, we can determine that the cause of the error is an empty file name argument passed to readPreferences(). Since readPreferences() knows that it can't handle empty file names, check the condition right away:

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 "quick failure"), the exception is clear and accurate.

The stack information immediately reflects what went wrong (providing an illegal parameter value), why something went wrong (the file name cannot be null), and what went wrong (the first part of readPreferences()). This way our stack information can be truthfully provided:

java.lang.IllegalArgumentException: filename is null

At jcheckbook.JCheckbook.readPreferences(JCheckbook.java:207)

At jcheckbook.JCheckbook.startup(JCheckbook.java:116)

At jcheckbook.JCheckbook. (JCheckbook.java: 27)

At jcheckbook.JCheckbook.main(JCheckbook.java:318)

In addition, the exception information contained in it ("file name is empty") makes the information provided by the exception richer by explicitly answering what is empty, and this answer is not provided by the NullPointerException thrown in our previous code.

Achieving rapid failure by throwing an exception immediately upon detection of an error can effectively avoid unnecessary object construction or resource usage, such as file or network connections. Similarly, the cleanup operations caused by opening these resources can be eliminated.

Delayed capture

One of the mistakes that rookies and masters can make is to capture a program before it can handle exceptions. The Java compiler indirectly encourages this behavior by requiring that the checked exception must be caught or thrown. The natural thing to do is to immediately wrap the code in a try block and use catch to catch the exception to prevent the compiler from reporting an error.

The question is, what should I do if I get an exception after the capture? The last thing you should do is to do nothing.

An empty catch block is equivalent to throwing the entire exception into a black hole, and all the information that tells when and why something went wrong will be lost forever. It's a little better to write the exception to the log, at least there are records to check.

But we can't expect users to read or understand log files and exceptions.

It is also inappropriate to have readPreferences() display an error message dialog, because while JCheckbook is currently a desktop application, we also plan to turn it into an HTML-based web application. In that case, displaying the error dialog is obviously not an option.

At the same time, regardless of the HTML or C/S version, the configuration information is read on the server, and the error information needs to be displayed to the web browser or the client program. readPreferences() should 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.

Capturing it prematurely before conditionally handling an exception usually results in more serious errors and other anomalies.

For example, if the readPreferences() method above captures and records a FileNotFoundException that may be thrown immediately when the FileInputStream constructor is called, the code will look like this:

Public void readPreferences(String filename){

//...

InputStream in = null;

// DO NOT DO THIS!!!

Try{

In = new FileInputStream(filename);

}

Catch (FileNotFoundException e){

Logger.log(e);

}

In.read(...);

//...

}

The above code captures it when it is completely incapable of recovering from a FileNotFoundException. If the file can't be found, the following method obviously can't read it.

What happens if readPreferences() is asked to read a file that does not exist? Of course, FileNotFoundException will be logged, and we will know if we go to the log file at the time.

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 will be thrown.

When debugging the program, the instinct tells us to see the last message of the log. That would be a NullPointerException, and what is very annoying is that this exception is very unspecified. The error message not only misleads us into something wrong (the real error is a FileNotFoundException instead of a NullPointerException), but also misleads the source of the error.

The real problem is that outside the number of rows where the NullPointerException is thrown, there may be several calls to methods and destruction of classes. Our attention was drawn by the little fish from the real mistakes, until we looked back at the logs to find the source of the problem.

Since what should readPreferences() really do is not to catch these exceptions, what should it be? It seems a bit irrational, and usually the most appropriate way is to do nothing, don't catch exceptions right away.

Give the responsibility to the caller of readPreferences() and let it investigate the appropriate way to handle the missing configuration file. It may prompt the user to specify another file, or use the default value. If it doesn't work, it may warn the user and quit the program.

The way to pass 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, the more specific the better. This is used to identify the type of exception that the program that called your method needs to know and is ready to handle. For example, the "delayed capture" version of readPreferences() might look 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 an IOException, but we explicitly declare that the method may throw a FileNotFoundException. An IllegalArgumentException is not mandatory because it is a non-checking exception (a subclass of RuntimeException). However, it is declared to document our code (these exceptions should also be noted in the JavaDocs of the method).

Of course, eventually your program needs to catch an exception, otherwise it will terminate unexpectedly.

But the trick here is to catch exceptions at the right level so that your program can either recover and continue meaningfully from the exception without causing deeper errors; or it can provide users with clear information, including guiding them from Recovery from the error. If your approach is not up to the task, then don't handle the exception, leave it behind and capture it at the right level.

in conclusion

Experienced developers know that the biggest difficulty in debugging a program is not to fix the defect, but to find the hiding place of the defect from the massive code. By following the three principles of this article, you can make your exceptions help you track and eliminate defects, making your program more robust and user-friendly.


Reels And Reel Stands

Cable Reel & Reel Stands of various types including Cable Reel Stand,Cable Stand,Reel Stand,Cabe Reel Jack,Cable Drum Elevator,Hydraulic Reel Stand,Hydraulic Drum Jacks,Cable Reel Trailer,Reel Trailer,which is specially used for lifting up cable drum and paying off conductors in electric power line project.It is made of high strength steel with reasonable volume,light weight,easy to operate.By high quality steel materials and good design(elevating height can be adjusted according to different reels),this kind of Cable Reel Stand & Trailers can be durable and long service life.we are a professional Chinese exporter of Hydraulic Cable Reel Stand & Trailers and we are looking forward to your cooperation.

Ningbo Marshine Power Technology Co. Ltd is specialized in manufacturing and trade of electric power line transmission tools. Our main products are Anti-twisting Steel Wire Rope,Stringing Pulley,Hydraulic Crimping Compressors,Engine Powered Winch,Motorised Winch,Wire Grip,Gin Pole,Cable Stand,Mesh Sock Grips,Cable Conveyor,Lever Chain Hoists and so on,which are mainly supplied to power companies,railroad companies and other industry fields.

All our products are certified by China National Institute.
To assure the quality, we will do 100% inspection for raw material, production procedure, packing before shipment,
so we do have the confidence to supply customers with high-quality and high-efficiency products.

"Customer satisfaction" is our marketing purposes,so we have extensive experience in professional sales force,and strongly good pre-sale, after-sale service to clients. We can completely meet with customers' requirements and cooperate with each other perfectly to win the market.Sincerely welcome customers and friends throughout the world to our company,We strive hard to provide customer with high quality products and best service.

Long-time Using Power Cable Reel

Rope Reel,Cradle Reel Stand,Upright Payout Turntable,Integrated Reel Stand,Hydraulic Conductor Reel Stands,Simple Reel Payout Stand,Portable Reel Stand

MARSHINE , https://www.puller-tensioner.com