Detailed Explanation of JAVA Exception and Exception Handling

Reprinted——JAVA Exception and Exception Handling Detailed
Reprinted from https://www.cnblogs.com/knightsu/p/7114914.html
1. Introduction to Exception
What is Exception?

Abnormality is different from the normal situation, different from the normal situation, and there are mistakes and mistakes. In java, a condition that blocks the current method or scope is called an exception.

What is the exception system in java?

1. All abnormal classes in Java inherit from the Throwable class. Throwable mainly includes two categories, one is the Error class and the other is the Exception class;

2. The Error class includes virtual machine errors and thread deadlocks. Once an Error occurs, the program will hang completely, which is called the program terminator;

3. The Exception class, which is commonly referred to as "abnormal". Mainly refers to problems with coding, environment, and user operation input. Exception mainly includes two categories, non-checked exception (RuntimeException) and checked exception (some other exceptions)

4. RuntimeException mainly includes the following four exceptions (in fact, there are many other exceptions, which are not listed here): null pointer exception, array subscript out-of-bounds exception, type conversion exception, and arithmetic exception. RuntimeException will be automatically thrown and captured by the java virtual machine (even if we don't write an exception capture statement, it will throw an error during runtime!!), the vast majority of such exceptions are problems with the code itself, which should be logically Fix and improve the code.

5. Check the exception. There are various reasons for the exception, such as the file does not exist, or a connection error, etc. Unlike its "brother" RuntimeException, we must manually add capture statements to the code to handle the exception. This is also the main exception object we deal with in learning java exception statements.

Two, try-catch-finally statement
(1) try block: responsible for catching exceptions, once an exception is found in try, the control of the program will be handed over to the exception handler in the catch block.

[The try statement block cannot exist independently, it must coexist with the catch or finally block]

(2) catch block: how to deal with it? Such as issuing warnings: prompting, checking configuration, network connection, logging errors, etc. After the catch block is executed, the program jumps out of the catch block and continues to execute the following code.

[Precautions for writing catch blocks: For exception classes handled by multiple catch blocks, the processing method of catching the subclass first and then catching the parent class should be followed, because the exception will be [handled nearby] (from top to bottom).

(3) finally: The code that is finally executed is used to close and release resources.

=======================================================================

The syntax format is as follows:

Copy code
Copy code
try { // some exceptions that will be thrown } catch (Exception e) { // the first catch // the code block that handles the exception } catch (Exception e) { // the second catch, you can There are multiple catch //blocks of code that handle the exception }finally{ //the final code to be executed } Copy code When an exception occurs, the program will terminate execution and be handed over to the exception handler (throwing a reminder or recording a log, etc. ), the code outside the exception code block is executed normally. try will throw many types of exceptions, and multiple catch blocks will catch multiple errors.












The order of multiple exception handling code blocks: first the subclass and then the parent class (the compiler will prompt an error if the order is wrong), and the finally statement block processes the code that will eventually be executed.

=======================================================================

Next, let's use examples to consolidate the try-catch statement~

Look at the example first:

Copy code
Copy code
1 package com.hysum.test;
2
3 public class TryCatchTest { 4 /** 5 * divider: divisor 6 * result: result 7 * try-catch capture while loop 8 * Each loop, divider minus one, result=result+100/divider 9 * If: catch exception, print out "exception thrown", return -1 10 * Otherwise: return result 11 * @return 12 */ 13 public int test1(){ 14 int divider= 10; 15 int result=100; 16 try{ 17 while(divider>-1){ 18 divider–; 19 result=result+100/divider; 20 } 21 return result; 22 }catch(Exception e){ 23 e. printStackTrace(); 24 System.out.println("Exception thrown!!"); 25 return -1;






















26 }
27 }
28 public static void main(String[] args) { 29 // TODO Auto-generated method stub 30 TryCatchTest t1=new TryCatchTest(); 31 System.out.println("The test1 method is executed! The value of result It is: "+t1.test1()); 32 } 33 34 } Copy code Copy code Running result:








Result analysis: The exception information thrown by the red word in the result is output by e.printStackTrace(), which shows that the exception type we throw here is an arithmetic exception, followed by the reason: by zero (caused by 0 Arithmetic exception), the following two lines at indicate the specific location of the code that caused this exception.

Add a test2() method to the above example to test the execution status of the finally statement:

Copy code
Copy code
1 /**
2 * divider: divisor
3 * result: result
4 * try-catch capture while loop
5 * Each loop, divider minus one, result=result+100/divider
6 * If: catch exception, Print out "An exception was thrown", return result=999
7 * otherwise: return result
8 * finally: print out "This is finally, hahaha!!" and print out result
9 * @return
10 */
11 public int test2 (){ 12 int divider=10; 13 int result=100; 14 try{ 15 while(divider>-1){ 16 divider–; 17 result=result+100/divider; 18 } 19 return result; 20 }catch( Exception e){ 21 e.printStackTrace(); 22 System.out.println("Exception thrown!!"); 23 return result=999; 24 }finally{













25 System.out.println("This is finally, hahaha!!");
26 System.out.println("The value of result is: "+result);
27 }
28
29 }
30
31
32
33 public static void main (String[] args) { 34 // TODO Auto-generated method stub 35 TryCatchTest t1=new TryCatchTest(); 36 //System.out.println("The test1 method is executed! The value of result is: "+t1.test1 ()); 37 t1.test2(); 38 System.out.println("test2 method is executed!"); 39 } Copy code Copy code Running result:








Result analysis: We can see from the results that the finally statement block is executed last after the try block and catch block statements are executed. finally is executed after the expression operation after return (at this time, the value after the operation is not returned, but the value to be returned is saved first, regardless of the code in finally, the returned value will not change, is still the previously saved value), so the return value of the function is determined before finally execution;

Here is an interesting question. If you add return to the finally statement block in the test2 method above, the compiler will prompt a warning: finally block does not complete normally

Copy code
Copy code
1 public int test2(){ 2 int divider=10; 3 int result=100; 4 try{ 5 while(divider>-1){ 6 divider–; 7 result=result+100/divider; 8 } 9 return result; 10 }catch(Exception e){ 11 e.printStackTrace(); 12 System.out.println("Exception thrown!!"); 13 return result=999; 14 }finally{ 15 System.out .println("This is finally, hahaha!!"); 16 System.out.println("The value of result is: "+result); 17 return result;//Compiler warning 18 } 19 20 } Copy code copy the code




















Analysis of the problem: The return statement in the finally block may cover the return statement in the try block and the catch block; if the return statement is included in the finally block, even if the previous catch block rethrows an exception, the statement calling the method will not The exception rethrown by the catch block will be obtained, but the return value of the finally block will be obtained, and the exception will not be caught.

Solving the problem: In the face of the above situation, it is actually more reasonable to neither use the return statement inside the try block nor use the return statement inside the finally, but use return after the finally statement to indicate the end and return of the function. like:

Summarize:

1. Regardless of whether there is an exception or there is a return value return in try and catch, the code in the finally block will be executed;

2. It is best not to include return in finally, otherwise the program will exit early, and the return will overwrite the return value saved in try or catch.

3. e.printStackTrace() can output exception information.

4. The return value -1 is the idiomatic way of throwing an exception.

5. If there is no return statement in try, catch, and finally in the method, the return result outside these three statement blocks will be called.

6. finally is executed after return in try and before returning to the calling function.

3. The throw and throws keywords
The exception throwing in java is usually implemented using the throw and throws keywords.

throw ----Throw the generated exception, which is an action of throwing an exception.

It is generally used when the programmer actively throws a specific type of exception when a certain logic occurs in the program. Such as:
  Syntax: throw (exception object), such as:

Copy Code
Copy Code
1 public static void main(String[] args) { 2 String s = “abc”; 3 if(s.equals(“abc”)) { 4 throw new NumberFormatException(); 5 } else { 6 System .out.println(s); 7 } 8 //function(); 9 } Copy code Copy code Running result:










Exception in thread "main" java.lang.NumberFormatException
at test.ExceptionTest.main(ExceptionTest.java:67)
throws----declare what type of exception will be thrown (declaration).

Grammar format:

1 public void method name (parameter list)
2 throws exception list { 3 // call the method that will throw an exception or: 4 throw new Exception(); 5 } is used for throws when a method may throw some kind of exception Declare the exception that may be thrown, and then hand it over to the method program that calls it from the upper layer. like:



Copy code
Copy code
1 public static void function() throws NumberFormatException{ 2 String s = “abc”; 3 System.out.println(Double.parseDouble(s)); 4 } 5 6 public static void main(String[] args ) { 7 try { 8 function(); 9 } catch (NumberFormatException e) { 10 System.err.println("Non-data types cannot be converted."); 11 //e.printStackTrace(); 12 } 13 } Copy code Copy code Comparison between throw and throws 1. Throws appears in the method function header; and throw appears in the function body. 2. Throws represents a possibility of exceptions, and these exceptions do not necessarily occur; throw means throwing an exception, and executing throw must throw some kind of exception object. 3. Both are passive ways to handle exceptions (the negative here does not mean that this method is not good), they just throw or may throw exceptions, but the exceptions will not be handled by the function, and the real exceptions are handled by the function Upper layer call processing.

















Let's look at an example:

Throws e1, e2, e3 just tell the program that this method may throw these exceptions, the caller of the method may have to deal with these exceptions, and these exceptions e1, e2, e3 may be generated by the function body.
Throw is to clarify that this place should throw this exception. like:

Copy code
Copy code
1 void doA(int a) throws (Exception1,Exception2,Exception3){ 2 try{ 3 … 4 5 }catch(Exception1 e){ 6 throw e; 7 }catch(Exception2 e){ 8 System.out .println("An error occurred!"); 9 } 10 if(a!=b) 11 throw new Exception3("Custom exception"); 12 } Copy code Copy code Analysis: 1. There may be 3 exceptions in the code block Exception, (Exception1, Exception2, Exception3). 2. If Exception1 is generated, it will be thrown after being caught, and the caller of the method will handle it. 3. If an Exception2 exception is generated, the method handles it by itself (that is, System.out.println("An error occurred!");). Therefore, this method will no longer throw Exception2, and void doA() throws Exception1, Exception2 in Exception3 does not need to be written. Because it has been captured and processed with a try-catch statement.

















4. Exception3 is an error in a certain logic of the method. The programmer handles it by himself. If Exception3 is thrown when the logic is wrong, the caller of the method must also handle the exception. A custom exception is used here, which will be explained below.

The following points need to be noted when using the throw and throws keywords:

1. The exception list of throws can be throwing one exception, or throwing multiple exceptions, each type of exception is separated by a comma

2. In the method body, call the method that will throw an exception or throw an exception first: use throw new Exception () throw to write in the method body, indicating the action of "throwing an exception".

3. If a method calls a method that throws an exception, you must add a try catch statement to try to catch this exception, or add a statement to throw the exception to a higher-level caller for processing

custom exception

Why use custom exceptions and what are the benefits?

1. When we are working, the project is developed by modules or functions. It is basically impossible for you to develop an entire project by yourself. Using custom exception classes unifies the way of external exception display.

2. Sometimes when we encounter some verification or problems, we need to end the current request directly. At this time, we can end it by throwing a custom exception. If you use a newer version of SpringMVC in your project, you have control To enhance the controller, you can write a controller enhancement class through the @ControllerAdvice annotation to intercept custom exceptions and respond to the corresponding information to the front end.

3. Custom exceptions can throw exceptions during some special business logic in our project, such as "neutral". Kind of unusual. Some errors in the system conform to the Java syntax, but do not conform to the business logic of our project.

4. Using custom exceptions to inherit related exceptions to throw processed exception information can hide the underlying exceptions, which is safer and the exception information is more intuitive. Custom exceptions can throw the information we want to throw, and we can distinguish the location of the exception through the thrown information. According to the exception name, we can know where there is an exception, and modify the program according to the exception prompt information. For example, the null pointer exception NullPointException, we can throw the message "xxx is empty" to locate the exception location without outputting the stack information.

After talking about why to use custom exceptions and what are the benefits, let's take a look at the problems of custom exceptions:

Needless to say, we cannot expect the JVM (Java Virtual Machine) to automatically throw a custom exception, nor can we expect the JVM to automatically handle a custom exception. The work of discovering exceptions, throwing exceptions, and handling exceptions must be done by the programmer using the exception handling mechanism in the code. This will correspondingly increase some development costs and workload, so if the project is not necessary, it does not necessarily have to use custom exceptions, and you must be able to weigh it yourself.

Finally, let's see how to use custom exceptions:

In Java you can customize exceptions. Here are a few things to keep in mind when writing your own exception classes.

All exceptions must be a subclass of Throwable.
If you want to write a checked exception class, you need to inherit the Exception class.
If you want to write a runtime exception class, you need to inherit the RuntimeException class.
You can define your own exception class like this:

class MyException extends Exception{ }

Let's look at an example:

Copy code
Copy code
1 package com.hysum.test;
2
3 public class MyException extends Exception { 4 /** 5 * error code 6 / 7 private String errorCode; 8 9 10 public MyException(){} 11 12 / * 13 * Construct a basic exception. 14 * 15 * @param message 16 * Information description 17 */ 18 public MyException(String message) 19 { 20 super(message); 21 } 22 23 24 25 public String getErrorCode() { 26 return errorCode; 27 } 28 29 public void setErrorCode(String errorCode) {


























30 this.errorCode = errorCode;
31 }
32
33
34 }
Copy Code
Copy Code
Use custom exception to throw exception information:

Copy Code
Copy Code
1 package com.hysum.test;
2
3 public class Main { 4 5 public static void main(String[] args) { 6 // TODO Auto-generated method stub 7 String[] sexs = {"male" , "female", "neutral"}; 8 for(int i = 0; i < sexs.length; i++){ 9 if("neutral".equals(sexs[i])){ 10 try { 11 throw new MyException("There is no neutral person!"); 12 } catch (MyException e) { 13 // TODO Auto-generated catch block 14 e.printStackTrace(); 15 } 16 }else{ 17 System.out.println (sexs[i]); 18 } 19 } 20 } 21 22 } Copy code Copy code Running result:





















It's that simple, you can throw corresponding custom exceptions according to actual business needs.

4. Exception chains in java Exceptions
need to be encapsulated, but encapsulation alone is not enough, and exceptions need to be passed.

Exception chaining is an object-oriented programming technique that refers to an exception handling method that wraps a caught exception into a new exception and rethrows it. The original exception is saved as an attribute (such as cause) of the new exception. The implication of this is that a method should throw exceptions defined at the same level of abstraction, but not discard lower-level information.

I can understand the exception chain like this:

Wrap the caught exception into a new exception, add the original exception to the new exception, and throw the new exception. They are like a chain reaction, one causes (cause) the other. In this way, the exception information thrown at the last top layer includes the exception information at the bottom layer.

"Scenario
For example, our JEE project generally has three layers: persistence layer, logic layer, and presentation layer. The persistence layer is responsible for interacting with the database, the logic layer is responsible for the realization of business logic, and the presentation layer is responsible for the processing of UI data.

There is such a module: when the user visits for the first time, the persistence layer needs to read the data from user. FileNotFoundException is discarded, the logic layer has no way of knowing what happened, and it cannot provide a friendly processing result for the presentation layer. In the end, it is the presentation layer that is unlucky: there is no way to provide exception information, and it can only tell the user "An error occurred, and I Don't know what's wrong"—not in a friendly way.

The correct way is to encapsulate first, and then transfer, the process is as follows:

1. Encapsulate FileNotFoundException as MyException.

2.抛出到逻辑层,逻辑层根据异常代码(或者自定义的异常类型)确定后续处理逻辑,然后抛出到展现层。

3.展现层自行确定展现什么,如果管理员则可以展现低层级的异常,如果是普通用户则展示封装后的异常。

》Example
Copy Code
Copy Code
1 package com.hysum.test;
2
3 public class Main { 4 public void test1() throws RuntimeException{ 5 String[] sexs = {"male", "female", "neutral"}; 6 for(int i = 0; i < sexs.length; i++){ 7 if("neutral".equals(sexs[i])){ 8 try { 9 throw new MyException("There is no neutral person! ”); 10 } catch (MyException e) { 11 // TODO Auto-generated catch block 12 e.printStackTrace(); 13 RuntimeException rte=new RuntimeException(e);// Wrapped into RuntimeException exception 14 //rte.initCause( e); 15 throw rte;//Throw a wrapped exception 16 } 17 }else{ 18 System.out.println(sexs[i]); 19 } 20 }

















21 }
22 public static void main(String[] args) { 23 // TODO Auto-generated method stub 24 Main m =new Main(); 25 26 try{ 27 m.test1(); 28 }catch (Exception e) { 29 e.printStackTrace(); 30 e.getCause();//Obtain the original exception 31 } 32 33 } 34 35 } Copy code Copy code Running result:















Result analysis: We can see that the console first outputs the original exception, which is output by e.getCause(); then it outputs e.printStackTrace(), where we can see Caused by: the original exception and e.getCause( ) output is the same. This is to form an exception chain. The role of initCause() is to wrap the original exception. When you want to know what abnormality happened at the bottom, you can get the original exception by calling getCause().

》It is suggested
that exceptions need to be encapsulated and transmitted. When we are developing the system, we should not "swallow" exceptions, and do not "nakedly" throw exceptions. Throw them after packaging, or pass them through the exception chain, so that the system can be more robust. friendly purpose.

5. Conclusion
The knowledge of exception handling in java is complicated and difficult to understand. Here I summarize the following points for you, good coding habits when using java exception handling:

1. When handling runtime exceptions, use logic to reasonably avoid and assist try-catch processing

2. After multiple catch blocks, you can add a catch (Exception) to handle exceptions that may be missed

3. For uncertain code, try-catch can also be added to handle potential exceptions

4. Try to handle exceptions as much as possible, remember to simply call printStackTrace() to print

5. How to deal with exceptions depends on different business requirements and exception types.

6. Try to add a finally statement block to release the occupied resources

Guess you like

Origin blog.csdn.net/weixin_42169551/article/details/109597626