Java understanding exceptions (super detailed)

Table of contents

Exception concepts and architecture

The concept of abnormality

Unusual architecture

Abnormal classification

1. Compile time exception

2. Runtime exception

Exception handling

defensive programming

LBYL

EAFP

Exception thrown

Exception catching

Exception declaration throws

try-catch capture and process

finally

Exception handling process


Exception concepts and architecture

The concept of abnormality

In Java, abnormal behavior that occurs during program execution is called an exception . For example, what is often encountered:

1. Abnormal arithmetic

System.out.println(10 / 0);

//Results of the

Exception in thread "main" java.lang.ArithmeticException: / by zero

2. Array out-of-bounds exception

int arr[] = {1, 2, 3};
System.out.println(arr[100]);

//Results of the

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException (array out of bounds exception): Index 100 out of bounds for length 3

3. Null pointer exception

int[] arr = null;
System.out.println(arr.length);

//Results of the

Exception in thread "main" java.lang.NullPointerException(空指针异常): Cannot read the array length because "arr" is null

As can be seen from the above process, different types of exceptions in Java have corresponding classes to describe them .

Note: When an exception occurs in the program, the code after the exception will not continue to be executed .

Unusual architecture

There are many types of exceptions. In order to properly classify and manage different exceptions or errors, Java maintains an exception architecture internally.

As you can see from the picture above:

1.Throwable: refers to the top-level class of exceptions, which derives two important subclasses, Error and Exception.

2. Error: refers to serious problems that cannot be solved by the Java virtual machine, such as: JVM internal errors, resource exhaustion , etc. Typical representatives: StackOverflowError (stack overflow error) and OutOfMemoryError ( out of memory error ) . Once it occurs, there is no way to recover.

3.Exception: After the exception is generated, the programmer can handle it through the code to continue the program execution.

Abnormal classification

Exceptions may occur during compilation or while the program is running. Depending on the timing of occurrence, exceptions can be divided into:

1. Compile time exception

Exceptions that occur during program compilation are called compile-time exceptions, also called checked exceptions (that is, they must be handled during compilation, otherwise the code will not pass)

public class Person {
    private String name;
    private String gender;
    int age;
    
    //想要让该类支持深拷贝,覆写Object类的clone方法即可
    
    @Override
    public Person clone() {
        return (Person)super.clone();
    }
}

//编译时报错
//Error:java:未报告的异常错误java.lang.CloneNotSupportedException;
//必须对其进行捕获或声明以便抛出

2. Runtime exception

Exceptions that occur during program execution are called runtime exceptions, also known as unchecked exceptions.

RunTimeException and the exceptions corresponding to its subclasses are called runtime exceptions . For example: NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException

Note: A syntax error occurs during compilation and cannot be called an exception . Such as spelling errors, etc. At this time, an error will occur during the compilation process. This is a compile-time error . The runtime refers to the errors that occur during the JVM execution after the program has been compiled and obtained the class file .

Exception handling

defensive programming

Errors exist objectively in the code. Therefore, we need to notify the programmer in time when there is a problem with the program.

main way

LBYL

Look Before You Leap. Do adequate inspections before operating. That is: defensive type beforehand

boolean ret = false;
ret = 登陆游戏();
if(!ret) {
    //处理登陆游戏时的错误;
    return;
}
ret = 开始匹配();
if(!ret) {
    //处理匹配错误;
    return;
}
ret = 游戏确认();
if(!ret) {
    //处理游戏确认错误
    return;
}
ret = 选择英雄();
if(!ret) {
    //处理选择英雄错误
    return;
}
...

Defects: The codes of the normal process and the error handling process are mixed together, and the overall code appears messy.

EAFP

It's Easier to Ask Forgiveness than Permission. "It's easier to ask for forgiveness afterward than to ask for permission beforehand." That is, operate first, and then deal with problems when they encounter them. That is, admitting mistakes afterwards

try {
    登录游戏();
    开始匹配();
    游戏确认();
    选择英雄();
    ...
} catch(登陆游戏时异常) {
    //处理登陆游戏时异常
} catch(开始匹配时异常) {
    //处理开始匹配时异常
} catch(游戏确认时异常) {
    //处理确认游戏时异常
} catch(选择英雄时异常) {
    //处理选择英雄时异常
}
...




Advantages: The normal process and error process are separated. Programmers pay more attention to the normal process. The code is clearer and easy to understand. The core idea of ​​exception handling is EAFP.

In Java, the five keywords for exception handling: throw, try, catch, final, throws

Exception thrown

When writing a program, if an error occurs in the program, the error information needs to be informed to the caller, such as: parameter detection

In Java, you can use the throw keyword to throw a specified exception object and inform the caller of the error message. The specific syntax is as follows:

throw new XXXException("The reason for the exception");

Ways to throw an exception: 1. Triggered by a certain program 2. Throw an exception through the throw keyword .

throw is generally used to throw custom exceptions .

For example: implement a method to get an element at any position in an array.

Precautions

1.throw must be written inside the method body

2. The object thrown must be Exception or a subclass object of Exception

3. If what is thrown is a RunTimeException or a subclass of RunTimeException, it does not need to be processed and can be left to the JVM for processing.

4. If a compile-time exception is thrown, the user must handle it, otherwise it will not pass compilation.

5. Once an exception is thrown, the subsequent code will not be executed.

Exception catching

There are two main types of exception capture, that is, the specific handling methods of exceptions: exception declaration: throws and try-catch capture processing.

Exception declaration throws

After the parameter list when the method is declared, when a compile-time exception is thrown in the method and the user does not want to handle the exception, you can use throws to throw the exception to the caller of the method for handling. That is, the current method does not handle exceptions and reminds the caller of the method to handle exceptions .

There are several ways to not handle exceptions in the method, but to throw the exception to the caller for processing:

1. Do not add exception handling code, directly do not add try-catch and other exception handling code, and let the exception be thrown inside the method.

public void method() {   // The operation may throw exceptions   throw new Exception(); } 2. Use throws to declare exceptions, and use the throws keyword in the method declaration to declare the types of exceptions that may be thrown.



public void method() throws Exception {   // ... } 3. Re-throw the exception. Use the throw statement to re-throw the exception after catching it.


public void method() {   try {   // ...   } catch (Exception e) {   throw e;    } } 4. Throw unchecked exceptions. For runtime exceptions, you can throw them directly without declaration.






public void method() {
  throw new RuntimeException();
}

Main grammatical format:

Modifier return value type method name (parameter list) throws exception type 1, exception type 2...{
 

}

For example: load the specified configuration file config.ini

public class Config {
    File file;
    /*
    FileNotFoundException:编译时异常,表明文件不存在
    此处不处理,也没有能力处理,应该将错误信息报告给调用者,让调用者检查文件名字是否给错误了
     */
    public void OpenConfig(String filename) throws FileNotFoundException {
        if(filename.equals("config.ini")) {
            throw new FileNotFoundException("配置文件名字不对");
        }
        //打开文件
    }
    public void readConfig() {
        
    }   
}

Precautions

1.throws must follow the method parameter list

2. The declared exception must be Exception or a subclass of Exception

3. If multiple exceptions are thrown inside the method, throws must be followed by multiple exception types, separated by commas. If multiple exception types are thrown and have a parent-child relationship, just declare the parent class directly.

public class Config {
    File file;
    //public void OpenConfig(String filename)throws IOException, FileNotFoundException {
    //FileNotFoundException继承自IOException
    public void OpenConfig(String filename) throws IOException {
        if(filename.endsWith(".ini")) {
            throw new IOException("文件不是.ini文件");
        }
        
        if(filename.equals("config.ini")) {
            throw new FileNotFoundException("配置文件名字不对");
        }
        
        //打开文件
    }
    
    public void readConfig() {
        
    }
}

4. When calling a method that declares to throw an exception, the caller must handle the exception or continue to use throws (the exception is not actually handled by the programmer, but is actually handed over to the JVM)

public static void main(String[] args) throws IOException {
    Config config = new Config();
    config.OpenConfig("config.ini");
}

try-catch capture and process

throws does not actually handle the exception, but reports the exception to the caller of the method that threw the exception, and the caller handles it, which requires try-catch.

The syntax format is as follows

try{
    //将可能出现异常的代码放在这里
} catch(要捕获的异常类型 e){
    /*如果try中的代码抛出异常了,此处catch捕获时的异常类型与try中抛出的异常类型
一致时,或者是try中抛出异常的基类型时,就会被捕捉到*/
    //对异常就可以正常处理,处理完成后,就会跳出try-catch结构,继续执行后续代码
} [{catch(异常类型 e) {
    //对异常进行处理
} finally {
    //此处代码一定会被执行到
}]

//后续代码
//当异常被捕获到时,异常就被处理了,这里的后续代码一定会被执行到
//如果捕获了,由于捕获时的类型不对,那就没有被捕获到,这里的代码就不会执行

Notice:

1. [ ] indicates optional items, which can be added or not added.

2. The code in try may throw an exception, or it may not

Let us continue the previous example and use try-catch to write this exception catching mode:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Config {
    File file;
    public void openConfig(String filename) throws FileNotFoundException {
        if(filename.equals("config.ini")) {
            throw new FileNotFoundException("配置文件名字不对");
        }
        //打开文件
    }
    public void readConfig() {

    }

    public static void main(String[] args) {
        Config config = new Config();
        try {
            //可能出现异常的代码
            config.openConfig("config.ini");
            System.out.println("文件打开成功");
        } catch(IOException e) {
            //异常的处理方式
            //System.out.println(e.getMessage());//只打印出异常信息
            //System.out.println(e);//打印异常类型:异常信息
            e.printStackTrace();//打印信息最全面
        }

        //一旦异常被捕获处理了,此处的代码会执行
        System.out.println("异常如果被处理了,这里的代码也可以执行");
    }
}

About exception handling

There are many types of exceptions, and we have to decide according to different business scenarios.

For more serious problems, the program should crash directly to prevent more serious consequences.

For less serious problems, error logs can be recorded and programmers can be notified in a timely manner through monitoring and alarm programs.

For problems that may be recovered (network-related scenarios), you can retry

In our current code, we adopt a simplified second method. The error log we record when abnormal method calls occur can quickly allow us to find the location of the exception. We will adopt a more complete approach in future work. way to record exception information.

Precautions

1. The code after the exception location in the try block will not be executed.

2. If the exception type thrown does not match the exception type when caught, that is, the exception will not be successfully caught and will not be handled. It will continue to be thrown until the JVM interrupts the program after receiving it - exceptions are caught according to the type.

3. Multiple different exceptions may be thrown in the try, and multiple catches must be used to catch them - that is, multiple exceptions and multiple catches ( although multiple exceptions can be caught, only one exception can be thrown at the same time )

If multiple exceptions are handled in the same way, this can also be done (not recommended)

catch(NullPointerException | ArrayIndexOutOfBoundsException e){...}

If there is a parent-child relationship between exceptions, the child class exception must be caught first and the parent class exception is caught later. Otherwise, the syntax is incorrect:

public class Test2 {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        try {
            System.out.println("before");
            arr = null;
            System.out.println(arr[0]);
            System.out.println("after");
        } catch(Exception e) {//Exceiom可以捕获到所有异常
            e.printStackTrace();
        } catch (NullPointerException e) {//永远都可以被执行到
            e.printStackTrace();
        }
        System.out.println("after try catch");
    }
}

4. All exceptions can be caught through one catch, that is, multiple exceptions, captured at once (not recommended: that is, you cannot use the parent class to receive all exception subclasses, which is inaccurate (it can be placed later to capture the last one)) 

Note: When catch performs type matching, it will not only match exception objects of the same type, but also capture subclass objects of the target exception type.

finally

When writing a program, there are some specific codes that need to be executed regardless of whether an exception occurs in the program, such as opening resources in the program: network connections, database connections, IO streams, etc. When the program exits normally or abnormally, the resources must be recycled. . In addition, some program jumps caused by exceptions may not be executed, and finally is used to solve this problem.

Syntax format:

try{
    //可能会发生异常的代码
    //如果这里有return,仍会执行finally,finally执行时机在return之前
}catch(异常类型 e){
    //对捕获的异常进行处理
}finally{
    //此处的语句无论是否发生异常,都会被执行到
}

The execution time of finally is before the method returns (if there is a return in try or catch, finally will be executed before this return). But if there is also a return statement in finally, the return in finally will be executed, so that it will not be executed in try. return. (It is generally not recommended to write return in finally)

Exception handling process

call stack

There is a mutual calling relationship between methods. This calling relationship can be described by a "call stack". There is a memory space in the JVM called the "virtual machine stack" that specifically stores the calling relationship between methods. When an exception occurs in the code, we can use e.printStackTrace() to view the call stack of the exception code

If there is no appropriate exception handling method in this method, it will be passed up the call stack. For example:

public class Test3 {
    public static void main(String[] args) {
        try{
            func();
        }catch(ArrayIndexOutOfBoundsException e){
            e.printStackTrace();
        }
        System.out.println("after try catch");
    }

    public static void func() {
        int[] arr = {1,2,3};
        System.out.println(arr[100]);
    }
}

Results of the:

Summary of exception handling process:

1. The program first executes the code in try

2. If an exception occurs in the code in try, the code in try will end to see if it matches the exception type in catch.

3. If a matching exception type is found, the code in catch will be executed.

4. If no matching exception type is found, the exception will be passed up to the upper caller.

5. Regardless of whether a matching exception type is found, the code in finally will be executed (executed before the end of the method

6. If the upper caller has no handled exception, continue to pass it upward.

7. There is no appropriate code to handle the exception until the main method, and it will be handed over to the JVM for processing. At this time, the program will terminate abnormally.

Guess you like

Origin blog.csdn.net/asdssadddd/article/details/132736668