I. Definition of exceptions
In Java programming ideology, an exception is defined as an exception that prevents the execution of the current method or scope from continuing. Although Java has an exception handling mechanism, to be clear, we should never treat exceptions with a "normal" attitude. In an absolute sense, exceptions are errors in a sense, that is, they may cause program failures. The reason why Java wants to propose an exception handling mechanism is to tell developers that your program is abnormal. Please note that.
I remember that when I first learned Java, I was always confused about exceptions. I don't know what this exception means. Why is there such a mechanism? However, with the accumulation of knowledge, I feel a little bit abnormal. For example, the purpose of an exception is described.
Public class calculator {public int devide (INT num1, int num2) {// determines whether the divisor is 0if (num2 = 0) {Throw new illegalargumentexception ("Division cannot be zero");} return num1/num2 ;}}
Let's take a look at the Division calculation method in this class. If you are a newbie, you may directly return the calculation result, without considering whether the parameters are correct or valid (of course, you can forgive me, ). However, we should try our best to minimize the possibility of program failure in the cradle, so it is necessary to check the legitimacy of parameters. The parameter thrown by the parameter check is invalid, which is abnormal in this method. Under normal circumstances, we will use the calculator correctly, but it is not ruled out to assign the divisor to 0 with carelessness. If you haven't considered this situation before and happen to have a poor mathematical foundation, you're done. But if you have considered this situation before, it is clear that the error is under your control.
Ii. Abnormal literacy
Today, when chatting with others, I saw a joke: the true feeling in the world is that you are trying to catch it. No matter how angry you are, I will handle it quietly. Most new users feel that Java exceptions are: Try... catch .... Yes, this is the most used and most practical. My feeling is: Java exceptions come from "try... catch.
First, familiarize yourself with Java's exception system:
The throwable class is the superclass of all errors or exceptions in the Java language (this is everything that can be thrown ). It has two subclasses: Error and exception.
Error: indicates a serious problem that a reasonable application should not attempt to capture. This is a big problem, so you can't handle it, so you just need to let it go. You don't have to worry about it. For example, virtualmachineerror: this error is thrown when the Java Virtual Machine crashes or uses up the resources required to continue operations. Well, even if this exception exists, how should we deal with it ?? Leave it to the JVM. It is no more professional than it.
Exception: it specifies the conditions that a reasonable application wants to capture. There are two types of exceptions: checkedexception and uncheckedexception. The main difference between the two types of exceptions is that checkedexception must be captured by try... catch..., while uncheckedexception does not need to be captured. Generally, uncheckedexception is also called runtimeexception. Warning Java states that the checkkedexception can be used for recoverable conditions, and the runtime exception (runtimeexception) can be used for program errors (unrecoverable by implication, leading to a big mistake ).
Our common runtimeexpiton include illegalargumentexception, illegalstateexception, nullpointerexception, indexoutofboundsexception, and so on. For those checkedexception, the exception caught by try... catch... is always checkedexception. Ioexception and its subclass in the IO package are all checkedexception.
Iii. Abnormal use
When exceptions are used, this part mainly demonstrates the Code. This is what we usually encounter when writing code (of course, it is only a small part!
Example 1: This example compares two methods to demonstrate the Code Execution Process after an exception occurs.
Public static void testexception1 () {int [] ints = new int [] {1, 2, 3, 4}; system. out. println ("before an exception occurs"); try {system. out. println (ints [4]); system. out. println ("do I still have the honor to execute it?"); // after an exception occurs, the subsequent Code cannot be executed} catch (indexoutofboundsexception e) {system. out. println ("array out-of-bounds error");} system. out. println ("when an exception occurs");}/* output: Before an exception occurs, array out-of-bounds error 4 after an exception */
Public static void testexception2 () {int [] ints = new int [] {1, 2, 3, 4}; system. out. println ("before an exception occurs"); system. out. println (ints [4]); system. out. println ("do I still have the honor to execute it?"); // after an exception occurs, the code behind it cannot be executed}
First, point out the shortcomings in the example. indexoutofboundsexception is a non-inspected exception, so try... catch... display capture, but my goal is to use different processing methods for the same exception to see what different results it will have (here we can only use it for a moment ). When an exception occurs, the first method only jumps out of the try block, but the code behind it will still be executed. However, the second method is not the same. It jumps out of the method and is tough. From the first method, we can see that try... catch... it is a kind of "transactional" protection. Its purpose is to ensure that the program runs normally, at the same time, it will also inform programmers of detailed information about errors in their programs (such details sometimes depend on the programmer's design ).
Example 2. Re-throw an exception
Public class rethrow {public static void readfile (string file) throws filenotfoundexception {try {bufferedinputstream in = new bufferedinputstream (New fileinputstream (File);} catch (filenotfoundexception e) {e. printstacktrace (); system. err. println ("I do not know how to handle this exception or do not want to handle it at all, but it is not appropriate to do not handle it. This is to throw an exception again and hand it to the next level for processing "); // throw an exception again. Throw E;} public static void printfile (string file) {try {readfile (File);} catch (filenotfoundexception e) {e. printstacktrace () ;}} public static void main (string [] ARGs) {printfile ("D:/file ");}}
The exception is intended to be good. Let's try to fix the program, but in reality we have a low chance of fixing it. We often use it to record error information. If you get tired of handling exceptions and throw exceptions again, it may be a good relief for you. The exception was thrown to the upper-level and the caller. Let him worry about it. In this case, the Java exception (of course, the checked exception) brings us a lot of trouble, even though its starting point is good.
Example 3: Abnormal link usage and loss
Define three exception classes: exceptiona, exceptionb, and exceptionc.
public class ExceptionA extends Exception {public ExceptionA(String str) {super();}}public class ExceptionB extends ExceptionA {public ExceptionB(String str) {super(str);}}public class ExceptionC extends ExceptionA {public ExceptionC(String str) {super(str);}}
Exception loss:
public class NeverCaught {static void f() throws ExceptionB{throw new ExceptionB("exception b");}static void g() throws ExceptionC {try {f();} catch (ExceptionB e) {ExceptionC c = new ExceptionC("exception a");throw c;}}public static void main(String[] args) {try {g();} catch (ExceptionC e) {e.printStackTrace();}}}/*exception.ExceptionCat exception.NeverCaught.g(NeverCaught.java:12)at exception.NeverCaught.main(NeverCaught.java:19)*/
Why does not I print exceptionc instead? Let's analyze it by yourself!
The above situation is equivalent to missing an exception, which is very unfavorable in our troubleshooting process. What should we do when we encounter the above situation? This is the application of the exception chain: saves the exception information and does not lose the original exception when another exception is thrown.
Public class nevercaught {static void F () throws exceptionb {Throw new exceptionb ("exception B");} static void g () throws exceptionc {try {f ();} catch (exceptionb e) {exceptionc c = new exceptionc ("Exception A"); // connects C. initcause (E); throw C ;}} public static void main (string [] ARGs) {try {G () ;}catch (exceptionc e) {e. printstacktrace () ;}}/ * exception. exceptioncat exception. nevercaught. G (nevercaught. java: 12) at exception. nevercaught. main (nevercaught. java: 21) caused by: exception. exceptionbat exception. nevercaught. F (nevercaught. java: 5) at exception. nevercaught. G (nevercaught. java: 10 )... 1 more */
The feature of this exception chain is available for all exceptions, because the initcause () method is inherited from throwable.
Example 4: cleanup
Cleaning is essential for us because some resource-consuming operations, such as Io and JDBC, are required. If we do not close it right after it is used up, the consequences will be very serious, which means memory leakage. The emergence of exceptions requires that we have to design a mechanism to clean up resources in a timely and correct manner under any circumstances. This is finally.
public void readFile(String file) {BufferedReader reader = null;try {reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));// do some other work} catch (FileNotFoundException e) {e.printStackTrace();} finally {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}
The example is very simple. It is an example of reading files. Such an example is also very common in JDBC operations. (So I think timely and correct resource clearance is one of the basic qualities of a programmer .)
The try... Finally structure is also a means to ensure that resources are properly closed. If you do not know what exceptions will occur during code execution and the resources cannot be cleaned up, use try to wrap this "suspicious" code, then, clear the resources in finally. For example:
public void readFile() {BufferedReader reader = null;try {reader = new BufferedReader(new InputStreamReader(new FileInputStream("file")));// do some other work//close readerreader.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} }
We should note the difference between this method and the previous method. The next person may get used to it better and close reader early. However, exceptions may occur at any time before reader. Close (). Such a code structure cannot prevent exceptions. Because the program will jump out of the exception and the subsequent Code cannot be executed (this should have been proved by the instance above ). Then we can use try... finally to transform it:
public void readFile() {BufferedReader reader = null;try {try {reader = new BufferedReader(new InputStreamReader(new FileInputStream("file")));// do some other work// close reader} finally {reader.close();}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
Closing resources early is a good behavior, because the longer you forget to close resources, the more likely you are. In this way, try... finally will ensure that everything is safe (don't be too troublesome, Java is just so reasonable ).
In another case, if I want to open a file in the constructor or create a JDBC connection, because we need to use this resource in other methods, therefore, you cannot close this resource early in the constructor. So we have no choice? The answer is no. Let's take a look at the following example:
public class ResourceInConstructor {BufferedReader reader = null;public ResourceInConstructor() {try {reader = new BufferedReader(new InputStreamReader(new FileInputStream("")));} catch (FileNotFoundException e) {e.printStackTrace();}}public void readFile() {try {while(reader.readLine()!=null) {//do some work}} catch (IOException e) {e.printStackTrace();}}public void dispose() {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}
This part introduces a little more, but exceptions do seem to be easy to use. Java still has many things to be dug up.
Iv. Misuse of exceptions
Misuse of exceptions is very common. I have already listed several exceptions in the previous section. Let's take a closer look. Let's talk about two other things.
Example 1. Catch all exceptions with an exception, which is quite "easy to understand. But this is also the most silly behavior.
public void readFile(String file) {BufferedReader reader = null;Connection conn = null;try {reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));// do some other workconn = DriverManager.getConnection("");//...} catch (Exception e) {e.printStackTrace();} finally {try {reader.close();conn.close();} catch (Exception e) {e.printStackTrace();}}}
From the exception perspective, such a strict program is indeed foolproof, and all exceptions can be captured. But from the programmer's point of view, how can we tell if this program goes wrong? IO or JDBC... so, it is worth taking as a counterexample. Don't think that this approach is very naive, and a fool will do it. During my internship at the company, I did see a similar situation: people did not use exception but throwable.
Example 2: here we will not give an example. The above programs are all counterexamples. Exceptions are the mechanism by which the program handles unexpected situations. When a program encounters an accident, we need to obtain as much unexpected information as possible, including the location, description, and cause of the accident. These are the clues for us to solve the problem. However, all the above examples are simple printstacktrace (). If we write code by ourselves, we need to describe this exception as much as possible. For example, why is this exception occurring and under what circumstances. If the parameters of the input method are incorrect, tell the parameter that is valid or give a sample.
Example 3. write the try block briefly. Don't leave everything here. We try to find out which lines of programs may have exceptions, just try the code that may have exceptions. Try to write a try... catch for every exception to avoid exception loss. In I/O operations, an ioexception also has the spirit of "being easy to use.
V. Summary
The summary is very simple. Do not use exceptions for exceptions. Exceptions are part of the program design and must be well-designed.