java exception handling mechanism

  This article is an original blog post, please indicate the source for reprinting, infringement must be investigated!

  The Java exception handling mechanism is frequently used in daily development, and the main ones are nothing more than a few keywords: try, catch, finally, throw, throws, and various Exceptions. This article mainly focuses on the basic usage methods, and further analyzes how to use the exception mechanism in development more reasonably.

  • try-catch-finally

    The try-catch-finally block is relatively simple to use and has the highest frequency of use. The try block contains statements that may cause exceptions (of course, this is a human decision, try can theoretically contain any code), the catch block is responsible for catching possible exceptions, and finally is responsible for executing the statements that must be executed, regardless of whether the code here occurs or not. exception will be executed.

    For this part, because it is very basic, here are some key suggestions:

      1. When you are writing a try-catch statement, you know in your mind which exception you want to deal with. Don’t just add a catch (Exception e) just in case, which is meaningless . In addition, there may be multiple exceptions in a try block. For each type of exception, a catch should be written to capture it.       

      2. Try-catch for statements that may cause exceptions. Try-catch for large sections of code will be very unfavorable for locating where exceptions may occur when maintaining the code. For stable code that will definitely not occur exceptions, do not need to be placed in try in the block.

      3. Although try-catch is functional, it can become a tool for process control to achieve the effect of conditional branching. However, compared with the if-else statement, Java's exception handling mechanism is based on object-oriented ideas, and requires more time and space overhead during use. Therefore, do not use the exception mechanism to make basic condition judgments. Catch and handle exceptions when interrupted.

      4. Never write a return statement in a finally block, because the finally block is always executed last, and it will change the expected return value in the try and catch blocks (for example, you catch an exception in catch and throw e , and return true in the finally statement, so that the exception you throw "disappears", because the execution result of the current function has changed from throwing an exception to returning true). In addition, when using resource objects and stream objects, the finally block must close the resource objects and stream objects.

  • Java Exception Architecture

    The base class of Java exception system is Throwable, which mainly has two subclasses: Error and Exception. Its structure is as follows:

      

    In the above figure, Error refers to the error that the program cannot handle, and mostly refers to the serious error inside the system. Most of these kinds of errors are not developer related, our main concern is Exception.

    Exception is mainly divided into two parts: runtime exception and non-runtime exception. Both RuntimeException and its subclasses are called runtime exceptions; otherwise, all subclasses of Exception are non-runtime exceptions.

    Run-time exceptions often refer to problems with program logic (that is, problems with our own code logic). Common errors include ClassCastException: type conversion exception, NullPointerException: null pointer exception, IndexOutOfBoundsException: out-of-bounds exception... These exceptions can be It can be avoided by program logic processing (such as adding a judgment statement to judge whether it is out of bounds, whether it belongs to a certain type, whether it is null), so the compiler gives these tasks to the programmer to control, even if a manual throws a Runtime exceptions are not caught, and the compiler will pass them. Therefore, this type of exception is also called "unchecked exception" (uncheck). Also belonging to unchecked exceptions are all Errors. That is, in the image above, all blue boxes represent unchecked exceptions, and orange boxes represent "checked exceptions" (check). For checked exceptions, try-catch blocks are used to catch and handle exceptions where the exception may occur. If it is not handled, it will be thrown to the upper layer until it is handled.

  • throw 与 throws

    throws关键字主要在方法签名中使用,用于声明该方法可能抛出的异常。throws 可以理解成是一种通知行为,没有实际的抛出异常的动作,而仅仅是告诉调用他的上层函数,这里可能会抛出这个异常;

    throw用于在函数体内语句中,表示抛出一个实际的异常的实际动作,如果在函数内没有捕获并处理,那么将会一直向上抛出这个异常直到被main()/Thread.run()抛出。

    当一个函数throws声明函数可能抛出一个非运行时异常(检查异常)时,那么即使这个函数内部不显示使用throw,调用它的上层函数也必须包含处理这个异常的代码。举个例子:

复制代码
public class Main {

    public static void main(String[] args){

        exceptionTest();
    }
    static int exceptionTest() throws IOException {
        
        return 0;    
    }
}
复制代码

    上述代码中调用的exceptionTest函数声明抛出一个IOException属于检查异常,哪怕exceptionTest函数中不可能抛出这个异常,调用它的函数也必须对此异常做出捕获处理。现在main函数中没有相关的处理逻辑,所以会编译错误,如下图:

    而对运行时异常,就是另一种情况了:

复制代码
 1 public class Main {
 2 
 3     public static void main(String[] args){
 4 
 5         int i = divideTest(0);
 6         System.out.println(i);
 7     }
 8     static int divideTest(int b) throws ArithmeticException {  
 9         
10         int i = 5/b;
11         return i;    
12     }
13 }
复制代码

    同样在main函数没有处理异常的逻辑,这次声明抛出的异常是ArithmeicException,他属于运行时异常(RuntimeException),所以编译器对声明的抛出置之不理:

        

    虽然编译期通过,但在运行时程序仍然会自动抛出运行时异常,并一直向上抛出到Main函数。而Main()中没有对该异常的捕获处理,所以主线程终止。

    结论:我目前的理解是,throws一个运行时异常是没有任何实际意义的,除非你为了遵循某个统一的规范而这样做。throws 存在的意义主要是将可能的非运行时异常交给编译器把关,让编译器监督开发人员对这些异常进行捕获处理。

    另外,当你需要自定义一个异常时,如果需要在编译期检查,并在上层统一处理,那么直接继承Exception成为一个检查异常;如果不需要编译期检查,抛出异常表示程序异常需要直接中断,那么继承RuntimeException成为一个运行时异常即可。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325790262&siteId=291194637