preface

Do you understand all the exception mechanisms in Java? Two head of a piece with you in simple, understand thoroughly.

Abnormal program

Exceptions are essentially errors in a program that occur frequently during the process of writing a program, both during compilation and during runtime.

  1. Error during compilation:

    This is usually a syntax error, which is beside the point, since nothing big happens to a program that doesn’t work.

  2. Runtime error:

    Some error procedures can not be managed, some error procedures should not be managed, and the error procedures must be managed. Runtime errors, if not handled properly, can lead to business problems that can spiral out of control.

What about runtime errors

When something goes wrong, we first have to know. How do we know? Java uses a try-catch statement to handle run-time errors. The keyword try is used to execute code that might have an error, and the keyword catch is used to catch the error.

public class Test {

    private static void printDiv(int dividend, int divisor) {
        System.out.println(dividend + "/" + divisor + "=" + (dividend / divisor));
    }

    public static void main(String[] args) {
        printDiv(10.5);
        printDiv(10.0);
        printDiv(10.2); }}Copy the code

The above code outputs 10/5, 10/0, and 10/2, respectively. However, the result shows that the program unexpectedly exits at 10/0, which is not a divisor.

Next, let’s modify the code to make our program compatible with exceptions.

public class Test {

    private static void printDiv(int dividend, int divisor) {
        try {
            System.out.println(dividend + "/" + divisor + "=" + (dividend / divisor));
        } catch(ArithmeticException e) {
            System.out.println(dividend + "/" + divisor + "Error occurred:"+ e.getMessage()); }}public static void main(String[] args) {
        printDiv(10.5);
        printDiv(10.0);
        printDiv(10.2); }}Copy the code

After handling the error using the try-catch syntax, you can see that when the program reaches the line of code where the error occurred, it will jump to the catch block and continue execution without another exception.

Catch which errors can be caught

All Throwable classes and their subclasses are captured in the cache. There are two classes of Error and Exception under Throwable. Any other error or exception should be inherited from both of them.

  1. Error:

    Errors are system-level errors that should not be captured and handled by the application, but rather by the system or framework.

  2. Exception:

    Exceptions are program-level errors that should be caught and handled by the program module.

How do I raise an exception

Our own code can also have exceptions. How do we initiate an exception? You can use the throw keyword.

public class Test {
	private static void someMethod(a) {
		// Throw an exception using the throw keyword
		throw new RuntimeException("An exception occurred during operation");
	}

	public static void main(String[] args) {
		someMethod();
		System.out.println("The master method is finished."); }}Copy the code

We can also throw Error and its subclasses, but in general we should throw Exception and its subclasses. I’ve talked about the difference before.

public class Test {
	private static void someMethod(a) {
		// Throw an error using the throw keyword
		throw new Error("An error occurred during operation");
	}

	public static void main(String[] args) {
		someMethod();
		System.out.println("The master method is finished."); }}Copy the code

We throw another exception and the compilation fails.

import java.sql.SQLException;

public class Test {
	private static void someMethod(a) {
		// Throw an exception using the throw keyword
		throw new SQLException("An exception occurred during operation");
	}

	public static void main(String[] args) {
		someMethod();
		System.out.println("The master method is finished."); }}Copy the code

Unchecked exceptions: Unchecked exceptions: Unchecked exceptions: Unchecked exceptions

  1. Checked Exceptions

    Except for RuntimeException and its subclasses, all Exception classes and their subclasses are searchable exceptions. The Java compiler checks for such exceptions, and when such exceptions occur in a program, either catch them with a try-catch statement or throw them with a throws clause declaration, otherwise the compilation will not pass.

  2. Unchecked exceptions (Unchecked exceptions)

    Unsearchable exceptions (exceptions that the compiler does not force to handle) : this includes runtimeExceptions (runtimeExceptions and their subclasses) and errors.

SQLException is one of the checked exceptions. We must either catch it with a try-catch, or declare it to be thrown. You can use the throws keyword.

import java.sql.SQLException;

public class Test {
	private static void someMethod(a) throws SQLException {
		// Throw an exception using the throw keyword
		throw new SQLException("An exception occurred during operation");
	}

	public static void main(String[] args) throws SQLException {
		someMethod();
		System.out.println("The master method is finished."); }}Copy the code

So it’s ready to compile.

Custom exception

Java already has a lot of built-in Error and Exception types that I won’t list because it’s easy to find. When the built-in Exception type doesn’t express our Error correctly, we can also customize the Error and Exception types by simply inheriting Error or Exception.

public class Test {
	/** * Custom exception type */
	static class MyRuntimeException extends RuntimeException {
		public MyRuntimeException(String message) {
			super(message); }}private static void someMethod(a) {
		// Throw an exception using the throw keyword
		throw new MyRuntimeException("An exception occurred during operation");
	}

	public static void main(String[] args) {
		someMethod();
		System.out.println("The master method is finished."); }}Copy the code

The posture of the try

There are three common positions for a try

public class Test {
    public static void main(String[] args) {
        / / position
        try {
            // The part that might throw an exception
        } catch (Exception e) {
            // Handling of exceptions
        }

        / / position 2
        try {
            // The part that might throw an exception
        } finally {
            // The part to be executed regardless of whether an exception occurs
        }

        / / position 3
        try {
            // The part that might throw an exception
        } catch (Exception e) {
            // Handling of exceptions
        } finally {
            // The part to be executed regardless of whether an exception occurs}}}Copy the code

All of the above methods are unified for error handling. What if a piece of code can have multiple errors, and I want to do a special treatment for one error?

import java.io.IOException;

public class Test {

    /** * write the result to a file *@param ret
     * @throws IOException
     */
    private static void writeFile(int ret) throws IOException {
        // I pretended to write the result to a file, which I didn't do, but that's my business
        throw new IOException("The disk is full.");
    }

    private static void printDiv(int dividend, int divisor) {
        try {
            int ret = dividend / divisor;
            System.out.println(dividend + "/" + divisor + "=" + ret);
            writeFile(ret);
        } catch(Exception e) {
            if (e instanceof IOException) {
                System.out.println(dividend + "/" + divisor + "An IO error occurred:" + e.getMessage());
            } else {
                System.out.println(dividend + "/" + divisor + "Error occurred:"+ e.getMessage()); }}}public static void main(String[] args) {
        printDiv(10.5);
        printDiv(10.0);
        printDiv(10.2); }}Copy the code

The above code achieves the desired effect, but it’s a little silly because Java already has the syntax to handle this situation directly. The following is the correct way, and the result is the same.

import java.io.IOException;

public class Test {

    /** * write the result to a file *@param ret
     * @throws IOException
     */
    private static void writeFile(int ret) throws IOException {
        // I pretended to write the result to a file, which I didn't do, but that's my business
        throw new IOException("The disk is full.");
    }

    private static void printDiv(int dividend, int divisor) {
        try {
            int ret = dividend / divisor;
            System.out.println(dividend + "/" + divisor + "=" + ret);
            writeFile(ret);
        } catch (IOException e) {
            System.out.println(dividend + "/" + divisor + "An IO error occurred:" + e.getMessage());
        } catch(Exception e) {
            System.out.println(dividend + "/" + divisor + "Error occurred:"+ e.getMessage()); }}public static void main(String[] args) {
        printDiv(10.5);
        printDiv(10.0);
        printDiv(10.2); }}Copy the code

One thing to note is that if we need to catch both the parent and the child, then the subclass must catch first, because Java matches in code order. If we write the parent’s catch block first, then the subclass’s catch block will never run to.

What if I were to group multiple exceptions that occur, some of which are handled in the first way, others in the second way, and others in the third way? Of course we could cache multiple times and have several cache blocks write the same thing, but that would still be silly. This is the right way.

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.WriteAbortedException;

public class Test {

    /** * write the result to a file *@param ret
     * @throws IOException
     */
    private static void writeFile(int ret) throws FileNotFoundException, WriteAbortedException {
        // I pretended to write the result to a file, which I didn't do, but that's my business
        int i = (int) (Math.random() * 3);

        switch (i) {
            case 0:
                throw new FileNotFoundException("File does not exist");
            case 1:
                throw new FileNotFoundException("File write interrupted");
            case 2:
                throw new FileNotFoundException("The disk is full."); }}private static void printDiv(int dividend, int divisor) {
        try {
            int ret = dividend / divisor;
            System.out.println(dividend + "/" + divisor + "=" + ret);
            writeFile(ret);
        } catch (FileNotFoundException | WriteAbortedException e) {
            System.out.println(dividend + "/" + divisor + "File write error occurred:" + e.getMessage());
        } catch (IOException e) {
            System.out.println(dividend + "/" + divisor + "An IO error occurred:" + e.getMessage());
        } catch(Exception e) {
            System.out.println(dividend + "/" + divisor + "Error occurred:"+ e.getMessage()); }}public static void main(String[] args) {
        printDiv(10.5);
        printDiv(10.0);
        printDiv(10.2); }}Copy the code

When do I need to use a finally block

Let’s start with the following code

import java.io.FileWriter;
import java.io.IOException;

public class Test {

	/** * Write to file *@param text
	 * @throws IOException
	 */
	private static boolean writeFile(String text) throws IOException {
		try {
			System.out.println("Request to Use resources");
			FileWriter fw = new FileWriter("test.txt");
			// An exception may occur after this
			fw.write(text);
			if (true) {
				throw new RuntimeException("Runtime exception");
			}
			// Close the stream resource, but an exception may occur before this happens
			System.out.println("Shut down resources");
			fw.close();
			return true;
		} catch (Exception e) {
			System.out.println("Handling exceptions:" + e.getMessage());
			return false; }}public static void main(String[] args) throws IOException {
		writeFile("test"); }}Copy the code

System resources, such as I/O streams, need to be released manually after they are applied from the system, otherwise leaks can occur. If an exception occurs before closing the resource, the program will jump to the catch block and continue executing. The code that closes the resource will never execute until the program exits. What to do? That’s when you need to finally.

import java.io.FileWriter;
import java.io.IOException;

public class Test {

	/** * Write to file *@param text
	 * @throws IOException
	 */
	private static boolean writeFile(String text) throws IOException {
		FileWriter fw = null;
		try {
			System.out.println("Request to Use resources");
			fw = new FileWriter("test.txt");
			// An exception may occur after this
			fw.write(text);
			if (true) {
				throw new RuntimeException("Runtime exception");
			}
			return true;
		} catch (Exception e) {
			System.out.println("Handling exceptions:" + e.getMessage());
			return false;
		} finally {
			if(fw ! =null) {
				System.out.println("Shut down resources"); fw.close(); }}}public static void main(String[] args) throws IOException {
		writeFile("test"); }}Copy the code

The above code has been modified to place the code that closes the resource ina finally block, which is executed regardless of whether an exception occurs in the try. Not only can resources be closed, but any logic that should be executed regardless of whether an exception occurs can be placed ina finally block.

Note also that an exception may occur ina catch block, but the code inside the finally block will still be executed.

import java.io.FileWriter;
import java.io.IOException;

public class Test {

	/** * Write to file *@param text
	 * @throws IOException
	 */
	private static boolean writeFile(String text) throws IOException {
		FileWriter fw = null;
		try {
			System.out.println("Request to Use resources");
			fw = new FileWriter("test.txt");
			// An exception may occur after this
			fw.write(text);
			if (true) {
				throw new RuntimeException("Runtime exception");
			}
			return true;
		} catch (Exception e) {
			System.out.println("Handling exceptions:" + e.getMessage());
			throw new RuntimeException("An exception occurred while handling an exception.");
// return false;
		} finally {
			if(fw ! =null) {
				System.out.println("Shut down resources"); fw.close(); }}}public static void main(String[] args) throws IOException {
		writeFile("test"); }}Copy the code

But if the finally block fails, the rest of the code will not continue.

import java.io.FileWriter;
import java.io.IOException;

public class Test {

	/** * Write to file *@param text
	 * @throws IOException
	 */
	private static boolean writeFile(String text) throws IOException {
		FileWriter fw = null;
		try {
			System.out.println("Request to Use resources");
			fw = new FileWriter("test.txt");
			// An exception may occur after this
			fw.write(text);
			if (true) {
				throw new RuntimeException("Runtime exception");
			}
			return true;
		} catch (Exception e) {
			System.out.println("Handling exceptions:" + e.getMessage());
			return false;
		} finally {
			if (true) {
				throw new RuntimeException("Finally block abnormal");
			}
			if(fw ! =null) {
				System.out.println("Shut down resources"); fw.close(); }}}public static void main(String[] args) throws IOException {
		writeFile("test"); }}Copy the code

Finally block code usually has to be executed, so to catch possible exceptions, try-catch syntax can be nested.

import java.io.FileWriter;
import java.io.IOException;

public class Test {

	/** * Write to file *@param text
	 * @throws IOException
	 */
	private static boolean writeFile(String text) throws IOException {
		FileWriter fw = null;
		try {
			System.out.println("Request to Use resources");
			fw = new FileWriter("test.txt");
			// An exception may occur after this
			fw.write(text);
			if (true) {
				throw new RuntimeException("Runtime exception");
			}
			return true;
		} catch (Exception e) {
			System.out.println("Handling exceptions:" + e.getMessage());
			return false;
		} finally {
			try {
				throw new RuntimeException("Finally block abnormal");
			} finally {
				if(fw ! =null) {
					System.out.println("Shut down resources"); fw.close(); }}}}public static void main(String[] args) throws IOException {
		writeFile("test"); }}Copy the code

The try – with – resources syntax

There are many cases of limited system resources such as IO streams, all of which need to be called off manually when they are finally used up. It’s silly to write template-like code every time, and in order for both a finally block and a try block to access that variable, you have to declare it outside of a try-catch, which causes code following the finally block to access that variable, which is unjustifiable. So later Java had new syntax to handle this situation. Classes that implement the AutoCloseable interface can be automatically closed.

import java.io.IOException;

public class Test {
	static class SomeResource implements AutoCloseable {
		public void use(a) {
			System.out.println("Use resources");
		}

		@Override
		public void close(a) {
			System.out.println("Shut down resources"); }}/** * Write to file *@param text
	 */
	private static boolean writeFile(String text) {
		try (SomeResource resource = new SomeResource();) {
			resource.use();
			// An exception may occur after this
			if (true) {
				throw new RuntimeException("Runtime exception");
			}
			return true; }}public static void main(String[] args) throws IOException {
		writeFile("test"); }}Copy the code

As you can see, the above code does not manually call the closing method when using the resource; the closing method is called automatically. The FileWriter we used previously already implements the AutoCloseable interface, so it can be automatically closed as well.

Multiple autoshutdown resources can be used in a block, in reverse order of initialization.

import java.io.IOException;

public class Test {
	static class SomeResource implements AutoCloseable {
		private final String name;

		SomeResource(String name) {
			this.name = name;
			System.out.println(Initialize resource: + name);
		}

		public void use(a) {
			System.out.println("Using resources:" + name);
		}

		@Override
		public void close(a) {
			System.out.println("Close resources:"+ name); }}/** * Write to file **@param text
	 */
	private static boolean writeFile(String text) {
		try (
				SomeResource resource1 = new SomeResource("Test Resource 1");
				SomeResource resource2 = new SomeResource("Test Resource 2");
				SomeResource resource3 = new SomeResource("Test Resource 3"); { resource2.use(); resource1.use(); resource3.use();// An exception may occur after this
			if (true) {
				throw new RuntimeException("Runtime exception");
			}
			return true; }}public static void main(String[] args) throws IOException {
		writeFile("test"); }}Copy the code

The end of the

The two masters have tried to write comprehensive, if there is not enough or inaccurate place, please forgive me, welcome to comment area discussion. And a triple, please. Thank you.