Java exception handling bad habits
Is it definitely a comprehensive mastery of Java's abnormal processing mechanism? In the following code, can you quickly find a few questions?
1 OutputStreamWriter out = ... 2 java.sql.connection conn = ... 3 try {// 4 statement stat = conn.createstatement (); 5 results = stat.executeQuery (6 "SELECT UID, Name from User" ); 7 While (rs.next ()) 8 {9 out.println ("ID:" rs.getstring ("uid") // 10 ", Name: rs.getstring (" name "); 11} 12 conn.close (); // 13 out.close (); 14} 15 catch (Exception ex) // 16 {17 ex.printstacktrace (); // 18}
As a Java programmer, you should at least be able to find two questions. However, if you can't find all six questions, please continue to read this article.
The general principles discussed in this article is not Java abnormal treatment, as these principles have been well known by most people. What we have to do is to analyze a variety of common bad habits that can be in violation of excellent coding specifications that can be known as "Anti-Pattern) to help readers are familiar with these typical backup examples, so they can detect and avoid these in actual work. problem.
One of the examples: discard abnormalities
Code: 15 lines-18 lines.
This code captures an exception but does not make any processing, you can calculate the killer in Java programming. From the perspective of frequentness and malfunction, it may comply with the issue of a bad name of the C / C program - do not check if the buffer is full. If you see this discard (rather than throwing) abnormalities, you can have problems in a percentage of codes (in a very small number of cases, this code has the reason, but it is best to add complete Comments, so as not to cause misunderstandings of others).
The error in this code is that an exception (almost) always means that something is wrong, or at least some unusual things have occurred, we should not maintain silence and indifferent to the rescue signal issued by the program. Call the printstackTrace countless "processing exception". Nice, call PrintStackTrace helps the debugger, but after the program debug phase ends, PrintStackTrace should not be responsible for the exception handling module.
The abnormality of discarding is very common. Open the document of the JDK's ThreadDeath class, you can see the following description: "Special, although ThreadDeath is a 'normal situation', the ThreadDeath class is an Error rather than the subclass of Exception, because many applications capture all Exception then discarding it no longer ignant. "This paragraph means that though ThreadDeath is a common problem, but in view of many applications try to capture all exceptions and then do not process, JDK defines ThreadDeath to define Error's subclasses, because the Error class represents a general application that should not capture serious problems. It can be seen that this bad habit of discarding anomalies is so common, and it has already affected the design of Java itself. So how should I correct? There are four options:
1. Treatment exception. Take some actions for this abnormality, such as correction issues, reminding someone or other processing, to determine the action that should be taken according to the specific situation. Once again, call PrintStackTrace is not "processed well".
2. Re-throw an exception. After processing an exception, after the analysis is abnormal, it is considered that he cannot handle it, and the re-throwing exception is not a choice.
3. Convert this abnormality into another exception. In most cases, this refers to an exception that converts a low level anomaly into an application level (its meaning is more susceptible to the user's abnormality).
4, do not capture exceptions.
Conclusion One: Since the exception is captured, it will be handled appropriately. Don't capture it after capture it and ignore it.
Two two: do not specify specific exceptions
Code: 15 lines.
Many times people will attract such a "wonderful" idea: capture all anomalies with a catch statement. The most common situation is to use the Catch (Exception EX) statement. But in fact, in most cases, this approach is not worth advocating. why?
To understand the reason, we must review the use of the catch statement. The Catch statement means that we expects some anomalies, and it is desirable to handle the exception. The action of an abnormality is to tell the Java compiler which exception we want to handle. Because most abnormalities are derived directly or indirectly from java.lang.exception, Catch (Exception EX) is equivalent to saying that we want to handle almost all exceptions.
Let's take a look at the previous code example. What is the exception we really want to capture? The most obvious one is SQLException, which is a common exception in the JDBC operation. Another possible exception is IOException because it is to operate OutputStreamWriter. Obviously, it is not appropriate to handle these two distinct abnormalities in the same CATCH block. If you capture SQLException and ioException, you will be much better. That is to say, the CATCH statement should try to specify the specific exception type without specifying the Exception class that covers a wide range. On the other hand, in addition to these two specific exceptions, there are many other abnormalities that may also occur. For example, if for some reason, ExecuteQuery returns NULL, what should I do? The answer is to let them continue to throw, that is, no need to capture. In fact, we should not catch all the exceptions that may have, and other places in the program also capture an exception - until the last is processed by JVM.
Conclusion II: Specify the specific exception type as much as possible in the catch statement, and multiple caratches are used if necessary. Do not try to process all possible exceptions.
Third, the three occupied resources are not released
Code: 3 line -14 lines.
An exception has changed the normal execution process. Although this truth is simple, it is often overlooked. If the program uses resources such as files, socket, JDBC connections, even if an exception is encountered, the resource occupied properly. To this end, Java provides a keyword for simplifying such operations. Finally is a sample: no matter whether there is an exception, Finally guarantees that the code to perform the cleaning task will always have the opportunity to perform before the TRY / CATCH / FINALL block end. Unfortunately, some people are not used to using Finally.
Of course, writing Finally blocks should be careful, especially to pay attention to the exception thrown within the Finally block - this is the last chance to perform the cleaning task, and try not to handle errors.
Conclusion 3: Ensure that all resources are released correctly. Make full use of Finally keywords.
Four of the antique example: Do not explain the detailed information code: 3 lines-18 lines.
Carefully observe this code: What happens if there is an abnormality inside the circulation? Can we get enough information to judge the cause of the loop within an error? No. We can only know that the class currently processed has a certain error, but it cannot obtain any information to determine the reason for the current error.
PrintStackTrace's stack tracking function displays execution processes running to the current class, but only provides some of the most basic information, failed to explain the reason for the actual error, and it is not easy to interpret.
Thus, when an abnormality occurs, some text information can be provided, such as the class, method, and other status information currently being executed, including the information provided by the PRINTSTACKTRACE in a more suitable reading.
Conclusion 4: Provide an appropriate amount of error reason in the abnormal processing module, organizing error information makes it easy to understand and read.
Reverse five: too huge TRY block
Code: 3 line -14 lines.
Often you can see someone put a lot of code in a single TRY block, in fact, this is not a good habit. This phenomenon is common, the reason is that some people have trouble, do not expect time to analyze which line of code will throw an exception, what is the specific type of exception. Put a large number of statements into a single huge try block is like going to travel, all daily supplies are put into a big box, although things are bringing, but it is not easy to find it.
Some newcomes often put a lot of code into a single TRY block, then declare Exception in the catch statement, rather than separating each paragraph, and capturing its exceptions separately. This approach has brought difficulties for analyzing procedures, because there are too many places in a large section possible to throw Exception.
Conclusion 5: Try to minimize the volume of the TRY block.
Reverse example: Output data is incomplete
Code: 7 line -11 lines.
Incomplete data is the invisible killer of the Java program. Carefully observe this code, consider what will happen if there is an abnormality in the middle of the loop. The execution of the loop is of course to be interrupted, secondly, Catch block will execute - there is no other action again. What should I do if the data has been output? People or devices using these data will receive an incomplete (and thus erroneous) data, but there is no prompt about whether this data is complete. For some systems, the data is incomplete may result in greater losses than the system stop running.
The more ideal means is to write some information to the output device, declare the incompleteness of the data; another possible effective way is to first buffer the data to be output, ready to output all the data again.
Conclusion Six: Comprehensively consider the possible abnormalities and the impact of these anomalies on the implementation process.
Record code
Based on the discussion above, the changed code will be given below. Maybe someone will say it is slightly awkward, but it has a more complete exception handling mechanism.
OutputStreamWriter out = ... java.sql.connection conn = ... try {statement stat = conn.createstatement (); ResultSet RS = stat.executeQuery ("SELECT UID, Name from User); while (rs.next )) {OUT.PRINTLN ("ID:" rgetstring ("UID") ", Name: rs.getstring (" name "));}} catch (sqlexception sqlex) {Out.println (" WARNING: Data is incomplete "); Throw new applicationException (" SQL error when reading data ", SQLEX);} catch (ioException ooex) {throw new applicationException (" IO error when writing data ", IOEX);} Finally {if (conn! = null) {type {conn.close ();} catch (sqlexception sqlex2) {system.err (this.GetClass (). getName () ".mymethod - You cannot close Database Connection:" SQLEX2.TOSTRING ());}}} f (out! = null) {Try} catch (ieException iex2) {system.err (this.getclass (). getname () ".mymethod - Do not turn off the output file " IOEX2.TOSTRING ());}}} The conclusion is not a tutor of four seas, sometimes common sense and experience is the best teacher. If you don't have a hundred percent confidence in your own practice, be sure to add a detailed, comprehensive annotation. On the other hand, don't joke these mistakes, ask if you really get rid of these bad habits. Even if the most experienced programmer occasionally, the reason is simple, because they have indeed brought "convenient". All of these antithractions can be seen as the devil of the Java programming world, they are beautiful, no hole, always tempting you. Perhaps someone will think that these are small things that belong to chicken skin garlic, but they are not stopped, but please remember: Don't be evil, don't be small and not.