1. Catch exception :

         stay Java in , Any statement that may throw an exception , Can be used try...catch capture . Put the statements with possible exceptions in try{...} in , Then use catch Capture the corresponding Exception And its subclasses .

        1. many catch sentence

                 Multiple can be used catch sentence , each catch Capture the corresponding Exception And its subclasses .JVM After an exception is caught , Will match from top to bottom catch sentence , Match to a catch after , implement catch Code block , Then stop matching . Simply put, multiple catch Only one statement can be executed . for example :
public static void main(String[] args) { try { process1(); process2();
process3(); } catch (IOException e) { System.out.println(e); } catch
(NumberFormatException e) { System.out.println(e); } }
                 There are multiple catch When ,catch The order of is very important , Subclasses must be written before , for example :
public static void main(String[] args) { try { process1(); process2();
process3(); } catch (IOException e) { System.out.println("IO error"); } catch
(UnsupportedEncodingException e) { // Never catch System.out.println("Bad
encoding"); } }
               
For the above code ,UnsupportedEncodingException Exceptions are never caught , Because it is IOException Subclass of , When thrown UnsupportedEncodingException Abnormal time , Will be catch(IOException
e){...} Capture and execute . therefore , The correct approach should be to put the subclass first :
public static void main(String[] args) { try { process1(); process2();
process3(); } catch (UnsupportedEncodingException e) { System.out.println("Bad
encoding"); } catch (IOException e) { System.out.println("IO error"); } }
       

        2.finally sentence  

               
No matter whether there is any abnormality , We all want to execute some statements , For example, clean-up work , You can write the execution statement several times : Place the normally executed try in , each catch Write it again , for example :
public static void main(String[] args) { try { process1(); process2();
process3(); System.out.println(" China will win in the fight against the epidemic !!!"); // This line of code is what we want to have to execute } catch
(UnsupportedEncodingException e) { System.out.println("Bad encoding");
System.out.println("END"); } catch (IOException e) { System.out.println("IO
error"); System.out.println("END"); } }
                 But this line of code is what we want to have to execute System.out.println(" China will win in the fight against the epidemic !!!"); 
But if an exception is thrown from the previously called method , You won't execute this line of code , Then we can use finally The statement block guarantees that it will be executed with or without errors , The above code can be rewritten as :
public static void main(String[] args) { try { process1(); process2();
process3(); } catch (UnsupportedEncodingException e) { System.out.println("Bad
encoding"); } catch (IOException e) { System.out.println("IO error"); } finally
{ System.out.println(" China will win in the fight against the epidemic !!!"); // This line of code is what we want to have to execute } }
                be careful finally Several characteristics of :

                        1.finally Statement is not required , You can write or not ;

                        2.finally Always last ;

               
If no exception occurs , It will be executed normally try{...} Statement block , Then execute finally. If an exception occurs , Interrupt execution try{...} Statement block , Then jump to execute the matching catch Statement block , Final execution finally. so finally It is used to ensure that some code must be executed .

                In some cases , We can also not catch, Just use try...finally Structural , for example :
void process(String file) throws IOException { try { ... } finally {
System.out.println(" China will win in the fight against the epidemic !!!"); // This line of code is what we want to have to execute } }
        3. Catch multiple exceptions :

                If the processing logic of some exceptions is the same , However, there is no inheritance relationship before the exception itself , Then you need to write multiple catch sentence , for example :
public static void main(String[] args) { try { process1(); process2();
process3(); } catch (IOException e) { System.out.println("Bad input"); } catch
(NumberFormatException e) { System.out.println("Bad input"); } catch (Exception
e) { System.out.println("Unknown error"); } }
                Because processing IOException and NumberFormatException The code is the same , So we can use it |
Merge together , for example :
public static void main(String[] args) { try { process1(); process2();
process3(); } catch (IOException | NumberFormatException e) { //
IOException or NumberFormatException System.out.println("Bad input"); } catch
(Exception e) { System.out.println("Unknown error"); } }
                use try...catch...finally Capture exception summary :

                        1. Multiple catch The matching order of statements is very important , Subclasses must be placed first .

                        2.finally Statement ensures that it will be executed with or without exceptions , It is optional .

                        3. One catch Statement can also match multiple exceptions that are not inherited .

2. Throw exception :

        1. Abnormal propagation route :

                When a method throws an exception , If the current method does not catch an exception , The exception will be thrown to the upper layer to call the method , Until you meet someone try...catch Until captured :
public class Main { public static void main(String[] args) { try { process1();
} catch (Exception e) { e.printStackTrace(); } } static void process1() {
process2(); } static void process2() { Integer.parseInt(null); //
Will throw NumberFormatException } }
                adopt printStackTrace() You can print out the call stack of the method , for example :
java.lang.NumberFormatException: null at
java.base/java.lang.Integer.parseInt(Integer.java:614) at
java.base/java.lang.Integer.parseInt(Integer.java:770) at
Main.process2(Main.java:16) at Main.process1(Main.java:12) at
Main.main(Main.java:5)
               
printStackTrace() Useful for debugging errors , The above information indicates :NumberFormatException Yes java.lang.Integer.parseInt Method , Look from bottom to top , The calling layers are :

                        1.main() call process1();

                        2.process1() call process2();

                        3.process2() call Integer.parseInt(String);

               
        4.Integer.parseInt(String) call Integer.parseInt(String,int);

                see Integer.java The source code is known , The code of the exception throwing method is as follows :
public static int parseInt(String s, int radix) throws NumberFormatException {
if (s == null) { throw new NumberFormatException("null"); } ... }

        2. Throw exception

                When an error occurs , For example, the user entered
Illegal character , We can throw an exception , How to throw an exception ? Refer to above Integer.parseInt() method , There are two steps to throw an exception :

                        1. Create a Exception Examples of ;

                        2. use throw Statement throw ;

                for example :
void process2(String s) { if (s==null) { NullPointerException e = new
NullPointerException(); throw e; //throw new NullPointerException(); } }
                In fact, most of the code that throws exceptions will be combined into one line, as commented above or below :
void process2(String s) { if (s==null) { throw new NullPointerException(); } }
                If a method catches an exception , Again catch Throw a new exception in self styled , It is equivalent to converting the thrown exception type :
void process1(String s) { try { process2(); } catch (NullPointerException e) {
throw new IllegalArgumentException(); } } void process2(String s) { if
(s==null) { throw new NullPointerException(); } }
               
When process2() Throw NullPointerException after , cover process1() capture , Then throw IllegalArgumentException(). If in main() Capture in IllegalArgumentException,wine Take a look at the print exception stack , as follows :
public class Main { public static void main(String[] args) { try { process1();
} catch (Exception e) { e.printStackTrace(); } } static void process1() { try {
process2(); } catch (NullPointerException e) { throw new
IllegalArgumentException(); } } static void process2() { throw new
NullPointerException(); } }
                The printed exception stack is similar to :
java.lang.IllegalArgumentException at Main.process1(Main.java:15) at
Main.main(Main.java:5)
               
This indicates that the new exception loses the information of the original exception or fundamental exception , We can no longer see the original exception NullPointerException Information about . In order to trace the complete exception stack information , When constructing exceptions , Put the original Exception Pass in the instance , new Exception You can hold the original Exception Information , Modify the above code as follows :
public class Main { public static void main(String[] args) { try { process1();
} catch (Exception e) { e.printStackTrace(); } } static void process1() { try {
process2(); } catch (NullPointerException e) { throw new
IllegalArgumentException(e); } } static void process2() { throw new
NullPointerException(); } }
                Run the above code , The printed exception stack is similar to , as follows :
java.lang.IllegalArgumentException: java.lang.NullPointerException at
Main.process1(Main.java:15) at Main.main(Main.java:5) Caused by:
java.lang.NullPointerException at Main.process2(Main.java:20) at
Main.process1(Main.java:13)
                be aware :Caused
by:Xxx, Description captured IllegalArgumentException Is not the root cause of the problem , The root cause is NullPointerException, Shi Zai Main.process2() Method . To get the original exception information in the code, you can use Throwable.getCause() method . If return null, It indicates that the exception is the fundamental exception causing the problem . With complete exception stack information , We can quickly locate and modify the code to solve the problem .

When an exception is caught and thrown again , Be sure to keep the original exception , In order to find the first crime scene faster !!!

                If we were try perhaps catch Exception thrown in statement block ,finally Will the statement block still execute ? for example :
public class Main { public static void main(String[] args) { try {
Integer.parseInt("abc"); } catch (Exception e) { System.out.println("catched");
throw new RuntimeException(e); } finally { System.out.println("finally"); } } }
                The execution result of the above code is as follows :
catched finally Exception in thread "main" java.lang.RuntimeException:
java.lang.NumberFormatException: For input string: "abc" at
Main.main(Main.java:8) Caused by: java.lang.NumberFormatException: For input
string: "abc" at ...
               
The first line is printed catchd, Description entered catch Statement block , The second line is printed finally, Instructions implemented finally Statement block , So we can know , stay catch When an exception is thrown in the , Will not affect finally Implementation of ,JVM Will execute first finally, Then throw an exception .

        3. Abnormal shielding :

                If in execution finally Exception thrown when statement , that catch Can the statement block continue to be thrown ? for example :
public class Main { public static void main(String[] args) { try {
Integer.parseInt("abc"); } catch (Exception e) { System.out.println("catched");
throw new RuntimeException(e); } finally { System.out.println("finally"); throw
new IllegalArgumentException(); } } }
                Execute the above code and find the exception information as follows :
catched finally Exception in thread "main" java.lang.IllegalArgumentException
at Main.main(Main.java:11)
               
Output description of console finally After throwing an exception , Originally in catch The exception to be thrown in the " disappear " Yes , Because only one exception can be thrown . Exceptions that are not thrown are called exceptions " Shielded " Exception of (Suppressed
Exception). In rare cases , We need to know all the anomalies , How to save all exception information ? The method is to save the original field with variables first , Then call Throwable.addSuppressed(), Add the original scene , Then in finally Throw in , as follows :
public class Main { public static void main(String[] args) throws Exception {
Exception origin = null; try { System.out.println(Integer.parseInt("abc")); }
catch (Exception e) { origin = e; throw e; } finally { Exception e = new
IllegalArgumentException(); if (origin != null) { e.addSuppressed(origin); }
throw e; } } }
                When catch and finally When exceptions are thrown , although catch The exception is masked , however finally The exception thrown still contains it :
Exception in thread "main" java.lang.IllegalArgumentException at
Main.main(Main.java:11) Suppressed: java.lang.NumberFormatException: For input
string: "abc" at
java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652) at
java.base/java.lang.Integer.parseInt(Integer.java:770) at Main.main(Main.java:6)
                adopt Throwable.getSuppressed() You can get all the Suppressed
Exception. In most cases , stay finally Do not throw exceptions in . therefore , We usually don't care Suppressed Exception.

                

                Exception thrown summary :

                        1. call printStackTrace() Exception propagation stack can be printed , Very effective for debugging programs ;

                        2. When an exception is caught and a new exception is thrown again , The original exception information should be held ;

                       
3. Usually not in finally Exception thrown in . If in finally Exception thrown in , The original exception should be added to the original exception , The caller can Throwable.getSuppressed() Get all added Suppressed
Exception.

3. Custom exception :

       
         When we need to throw an exception in our code , Try to use JDK Defined exception . for example : Illegal parameter type , We should throw IllegalArgumentException:
static void process1(int age) { if (age <= 0) { throw new
IllegalArgumentException(); } }
               
Of course, in large projects , You can customize new exception types , however , It is very important to maintain a reasonable inheritance system , The usual approach is to customize an exception as " Root anomaly ", then , Derive exceptions of various business types . The root exception needs to be from a suitable one Exception derive , It is usually recommended to start from RuntimeException derive :
public class BaseException extends RuntimeException { }
                Other exception types can be derived from the root exception :
public class UserNotFoundException extends BaseException { } public class
LoginFailedException extends BaseException { } ...
                The custom root exception should provide multiple construction methods ( Better with RuntimeException corresponding ):
public class BaseException extends RuntimeException { public BaseException() {
super(); } public BaseException(String message, Throwable cause) {
super(message, cause); } public BaseException(String message) { super(message);
} public BaseException(Throwable cause) { super(cause); } }
                Refer to the above construction method RuntimeException Native implementation . such , When throwing an exception , You can choose the appropriate construction method .

                Custom exception summary :

                        1. When throwing an exception , Reuse as much as possible JDK Defined exception types ;

                        2. When customizing exception system , Suggest from RuntimeException Class derived root exception , Other types of exceptions are then derived from the root exception .

                        3. Custom exception , Try to imitate RuntimeException class , Provides a variety of construction methods .

Technology