Java exception handling mechanism

Posted by jamesl73 on Mon, 01 Nov 2021 12:55:28 +0100

1. What is a Java exception

Anomalies in our life are some unusual and abnormal phenomena. In Java, exceptions refer to some errors in the program, that is, the program does not go in the direction we want. For example: the data passed in by a module we wrote does not meet your requirements; You access online services, but your network connection fails; The data you query in the database is empty; The file you accessed does not exist or the format of the file is different from what you think; When the program is running, the JVM makes an error or runs out of memory space, etc. These exceptions occur during program operation and interrupt the normal instruction flow of the executing program.

1.1 exception architecture

In Java, all exceptions are objects. They have one thing in common. The parent class is Throwable. The inheritance diagram is as follows

Throwable is the ancestor of all Exception classes. It includes two important subclasses: Error and Exception.

1.2. Anomaly classification

Error class

The Error class and its subclasses are used to describe internal errors and resource exhaustion errors in the Java running system. Such errors cannot be handled by the program and are more serious. The occurrence of this Error is generally independent of the coder, and the JVM generally selects thread termination when this Error occurs, because this situation is outside the processing scope of the program, which can not be handled only by the program itself, and the Java program will not catch and throw the Error exception.

Exception class

Exception exception can be caught to make the program continue to execute. It is an exception that the program itself can handle, also known as non fatal exception.

According to the cause of the error, it can be divided into runtime exception and checkedexception

  • Runtime exception: exception of RuntimeException class and its subclasses. Such as incorrect type conversion, array access out of bounds, access to null pointers, etc. This kind of exception is generally caused by the logic error of the program. The program should avoid this kind of exception as far as possible from the logic point of view. This exception can be either caught or not handled. This kind of exception will not be checked by the Java compiler, that is, when the program has a running exception, it will also be compiled. It can be said that if RuntimeException occurs, it must be your problem.
  • Check exceptions: all non running exceptions can be classified as check exceptions. For example, trying to read data after the end of a file, trying to open a non-existent file, trying to find a Class object according to a given string, and the Class represented by this string does not exist. Such exceptions cannot be foreseen by the program ape. For example, if we want to open a nonexistent file, an exception occurs. These exceptions cannot be ignored during compilation. Without handled check exceptions, the program cannot be compiled successfully.

2. Exception handling mechanism

People feel bad when they make mistakes. If a user loses user data during running the program due to program errors or the influence of some external environment, the user may no longer use the program. In order to avoid such things, at least the following points should be done:

  • Notify users of errors;
  • Save all work results;
  • Allow the user to exit the program in a proper form.

For exception situations, such as error input that may cause program crash, Java uses an error capture mechanism called exception handling.

In Java applications, the exception handling mechanism is to throw exceptions and catch exceptions.

2.1. Throw an exception

When a method raises an exception due to an error, the method creates an exception object and delivers it to the runtime system. The exception object contains exception information such as exception type and program state when the exception occurs. The runtime system is responsible for finding and executing the code to handle exceptions.

Methods for throwing exceptions: throws and throw

  • Throws: exceptions that may be thrown by the declaration method. Multiple exceptions are common and separated. Throws keyword throws the object to the upper level. If you don't want to handle it, you can continue to throw it up, but finally there must be an operation that can handle the exception. Syntax format: method name (parameter) throws exception 1, exception 2... Exception n.
  • Throw: used in the method body or throw custom exceptions. The program stops immediately when the throw statement is executed. If you want to catch the exceptions thrown by throw, you must use the try catch statement. Syntax format throw exception object.

Example: throws

public class Main {
    public static void popException() throws ArrayIndexOutOfBoundsException{
        int[] arr = new int[1];
        arr[2]  = 8;
    }

    public static void main(String[] args) {
        try {
            popException();
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Array out of bounds exception!");
        }
    }
}

Example: throw

public class Main {
    public static void popException(int value) {
        if (value == 0) {
            throw new ArithmeticException("value Cannot be zero!");
        }
    }

    public static void main(String[] args) {
        try {
            popException(0);
        } catch (ArithmeticException e) {
            System.out.println(e.getMessage());
        }
    }
}

be careful:

  • throw statements are not allowed to be followed by other statements because they have no chance to execute.
  • If a method calls another exception thrown with the throws declaration, the method either handles the exception or continues to throw.
  • throw statement throws two exceptions:
    • When the exception thrown by the throw statement is a Checked exception, the throw statement either explicitly catches the exception in the try block or puts it in a method thrown with the throws declaration, that is, the exception is handed over to the caller of the method for processing.
    • When the exception thrown by the throw statement is a Runtime exception, the statement does not need to be placed in the try block or in the method thrown with the throws declaration. The program can either explicitly use try... Catch to catch and handle the exception, or ignore the exception completely and hand the exception to the caller of the method for processing.

2.2. Capture exceptions

We already know how to throw or throw exceptions. At the same time, in the above example, we also briefly explained how to catch exceptions, that is, to catch exceptions through the try..catch statement.

If no exception operation is caught, once an exception occurs, the console will print the exception type and its stack trace. As follows:

public class Main {
    public static void popException(int value) {
        if (value == 0) {
            throw new ArithmeticException("value Cannot be zero!");
        }
    }

    public static void main(String[] args) {
        popException(0);
    }
}

So when we debug the program, we can check the stack trace to find out the specific location of our error!

2.2.1. try... catch statement

The following is a simple try..catch statement:

public static void main(String[] args) {
    try {
        popException(0);
    } catch (ArithmeticException e) {//Catch exception
        //Handling ArithmeticException exception
    }
}

Features of try..catch statement:

  • If any code in the try statement block throws an exception class specified in the catch sentence, the program skips the rest of the code in the try statement block, and then jumps to the catch statement to handle this kind of exception.
  • If no exception is thrown in the try statement block, the catch clause is skipped.
  • If the code in the try statement block runs out of an exception that is not declared in the catch statement, the method exits immediately (throwing an exception to the caller by default).

Example:

public class Main {
    public static void popException(int value) throws ArithmeticException{
        int i = 4;
        while (value >= 0) {
            System.out.println("result" + i / value--);
        }
    }

    public static void main(String[] args) {
        try {
            popException(2);
            System.out.println("The code has been executed for 12 lines!");
        } catch (ArithmeticException e) {
            System.out.println("Catch exception divisor is zero!");
        }
    }
}

2.2.2. finally statement

Once the code throws an exception, it stops the remaining code of the method and pushes the method. If the method has obtained some local resources that only it knows before throwing an exception, these resources must be cleaned up, and a problem arises.

One solution is to catch the exception first, clean up the resources and throw the exception again, but this method is cumbersome, because we have to clean up the resources when the exception occurs and clean up the resources when the exception does not occur, which is equal to the same operation. We have written the code twice. In java, we can use finally to implement the above operations.

Whether or not an exception is caught, the statement in finally will be executed. The general writing method is as follows (take the file input stream as an example):

try {
    FileInputStream in = new FileInputStream(...);
    //Operate on the file input stream
} catch (IOException e) {
    //Handling exceptions
} finally {
    //Close file input stream
    in.close();
}

finally features:

  • No matter whether an exception occurs or not, the finally statement will be executed. If a return statement is placed in the finally statement, all the return statements in try and catch will be invalid, but we generally do not do so.
  • finally statement will not be executed when
    • Exit the program with System.exit() before executing the finally statement.
    • An exception occurred in the finally statement.
    • The thread on which the program is located dies.
    • CPU shutdown.
  • Try, catch and finally cannot be used alone. They can only be try catch, try finally or try catch finally.

The following example gives you a deep impression of the try..catch..finally statement:

public class Main {
    public Main() {
    }

    boolean testEx() throws Exception {
        boolean ret = true;
        try {
            ret = testEx1();
        } catch (Exception e) {
            System.out.println("testEx, catch exception");
            ret = false;
            throw e;
        } finally {
            System.out.println("testEx, finally; return value=" + ret);
            return ret;
        }
    }

    boolean testEx1() throws Exception {
        boolean ret = true;
        try {
            ret = testEx2();
            if (!ret) {
                return false;
            }
            System.out.println("testEx1, at the end of try");
            return ret;
        } catch (Exception e) {
            System.out.println("testEx1, catch exception");
            ret = false;
            throw e;
        } finally {
            System.out.println("testEx1, finally; return value=" + ret);
            return ret;
        }
    }

    boolean testEx2() throws Exception {
        boolean ret = true;
        try {
            int b = 12;
            int c;
            for (int i = 2; i >= -2; i--) {
                c = b / i;
                System.out.println("i=" + i);
            }
            return true;
        } catch (Exception e) {
            System.out.println("testEx2, catch exception");
            ret = false;
            throw e;
        } finally {
            System.out.println("testEx2, finally; return value=" + ret);
            return ret;
        }
    }

    public static void main(String[] args) {
        Main main = new Main();
        try {
            main.testEx();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.2.3. try... with... Resources statement

After java 7, a try... With... Resources statement appears, that is, a try statement with resources. The following is a simple try... With... Resources statement:

try (Resource res = ...) {
    //Use of res
}
	Simply put, in try It will be called automatically after execution`res.close()`. If you try to use this method when using resources, reduce the amount of code.

2.3. User defined exception

During development, we will encounter many exceptions that cannot be described by standard Exception classes. In this case, it is important to create your own Exception class. When creating, we only need to create a class or subclass that inherits Exception. Generally, a custom Exception class contains two constructors, one is the default constructor, and the other is the constructor containing detailed information. For example:

//Custom exception to judge whether the length is legal
public class LengthException extends Exception {
    public LengthException() {}
    public LengthException(String s) {
        super(s);
    }
    @Override
    public String getMessage() {
        return super.getMessage();
    }
}

Next, it's the same as throwing an exception before.

2.4. Skills of using exceptions

  • Exception handling does not represent a simple test.
  • Don't over subdivide exceptions.
  • Make full use of exception hierarchy * * (try to use accurate exception class description) * *.
  • Do not suppress * * (capture does not handle) * * exceptions.
  • When detecting errors, "harsh" is better than laissez faire.
  • Don't be shy about passing exceptions.

3. References

https://blog.csdn.net/zx64881926/article/details/52300271
Java Core technology Volume I

Topics: Java