This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021

Author: White Snail

What is an exception

We often meet some unexpected things in our daily life, such as taking the train without id card, then you can’t get on the train smoothly.

The computer world has a similar situation, and the term is Exception, which is short for Exception Event.

An exception is an event that occurs during program execution and interrupts the normal operation of the program. For example, if you get on the train without id card, this is an abnormal event, and this event will prevent you from getting on the train normally.

Computer programs run with a main entry, usually called the main method, and various other methods may be called from inside the main method. When something goes wrong with a method, the method creates an object and passes it to the runtime system. This object is called the exception object, and it contains error-related information, including the error type and program status.

The action of creating an exception object and handing it to the runtime system is called throwing an exception.

When a method throws an exception, the runtime system tries to find a way to handle the exception. First, the system determines whether the method in which the error occurred has been handled. If not, it throws the exception to the upper method until it finds a method with exception handling. In this way, an ordered list of methods is formed between the method where the error occurred and the method where the exception was handled.

This list of methods is called the Call stack. Application of each method will be in call order into the stack and the stack is advanced, after the main method of advanced stack, for example, began to execute a program, meet other method calls, other methods into the stack, and other methods has been completed other way out of the stack, continue to implement the main method, the main method is done out of the stack, stack is empty, the program is running over.

The runtime system looks for a method in the call stack that contains a block of code that can handle an exception, called an exception handler. Through the call stack, starting with the method where the error occurred and looking for method calls in the reverse order (the stack has a first-in, last-out characteristic). When a suitable exception handler is found, the runtime system passes the exception to the handler. An exception handler is considered appropriate if the type of the exception object thrown matches the type the handler can handle.

The process of selecting an exception handler is called catching an exception.

If the run time system has searched all the methods on the call stack and still cannot find the appropriate exception handler, the run time system (and subsequent programs) will terminate.

Look at the following code and think about how it works.

package com.springtest.demo;

public class Test {

    /** * program main method **@paramArgs program entry parameter */
    public static void main(String[] args) {

        // The user enters the string woniu
        String woniu = "woniu";

        int num = str2number(woniu);

        System.out.println(num);
    }

    /** * STR to integer **@paramSTR string *@returnInteger * /
    private static int str2number(String str) {

        // Parse into numbers and throw NumberFormatException
        returnInteger.parseInt(str); }}Copy the code

The output looks like this:

Exception in thread "main" java.lang.NumberFormatException: For input string: "woniu"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.lang.Integer.parseInt(Integer.java:615)
	at com.springtest.demo.Test.str2number(Test.java:29)
	at com.springtest.demo.Test.main(Test.java:15)
Copy the code

When we look at the result information, we see that the main application is abnormal and the program is aborted because the value of num is not printed.

NumberFormatException = woniu; NumberFormatException = woniu; This is in line with our expectations.

Then there is the call stack, where each line of information identifies the method path, class name, and number of lines of code in the abnormal flow.

The first line of information is where the exception occurs first, which can also be used as the basis for our exception detection.

It is clear that after forInputString throws an exception, parseInt and str2Number simply forward the exception and do not catch it, even in the main method. Finally, the program is aborted because there is no exception handler.

How do I catch and handle exceptions

In order for a program to run without accidental termination, the Java programming specification requires that exceptions be caught or specified.

Use the try

The first step in catching an exception is to surround the code that might throw the exception with **try**.

The syntax is as follows:

try {
    // Code that may throw an exception
}

Copy the code

Try contains a code block where you can put code that might raise an exception. The code can be one line or multiple lines. This also means that this block of code can throw many different exceptions.

Exception handlers alone try will not compile. If you use javac to compile a Java file with only a try, you will get the following error:

Error:'try'Without a'catch'.'finally'Or resource declarationtry{^1A mistakeCopy the code

So the try block simply defines the scope of the exception to be caught, and it’s not enough to do exception management alone.

The use of the catch

Catch the grammar

So catching an exception requires the second step: catch the exception and handle it.

The syntax is as follows:

try {
    // Code that may throw an exception
} catch (ExceptionType1 name1) {
    Exception handling code for ExceptionType1 ExceptionType1
} catch (ExceptionType2 name2) {
    Exception handling code for ExceptionType2 ExceptionType2
}
Copy the code

A catch is used with a try, not by itself. A try can be followed by multiple catch blocks to handle the many types of exceptions that occur in a try.

Each catch block is an exception handler whose type is specified by the parameters of the catch.

In the parentheses of catch, the argument ExceptionType declares the ExceptionType that the handler can handle. This ExceptionType must be a class inherited from the Throwable class.

Java exception inheritance system

When it comes to Throwable, Java’s exception system has to be mentioned. The following is an inheritance architecture diagram for Java exceptions.

ThrowableIs the root of the exception system, which inherits from Object.ThrowableAnd divided into two systems:ErrorException.

An Error represents a serious Error that a program generally cannot handle, such as a StackOverflowError indicating a stack overflow.

Exception represents a runtime error that can be caught and handled. Exception can be split into two classes: RuntimeException and Checked Exception.

RuntimeException refers to a runtime exception, it is to write the wrong program logic, such as null pointer exception said NullPointerException array index and said the IndexOutOfBoundsException cross. Such exceptions are code bugs and should be fixed.

int[] arrry = {0.1.2};

/ / here will throw Java. Lang. ArrayIndexOutOfBoundsException, should not appear arrry [3] this code
System.out.println(arrry[3]);
Copy the code

Checked Exception is a Checked Exception that is part of the program logic. Examples include IOException (indicating an IO exception) and FileNotFoundException (indicating that the file could not be found). This exception must be caught and handled, or the compilation will fail.

The following code will not compile:

public class A {
    public static void main(String[] args) {

        FileInputStream inputStream = new FileInputStream("/"); }}Copy the code

The javac compilation will report the following error, and it will also tell you that you must catch the exception with a try/catch or add the exception to the declaration to make it easier to throw.

Error: Unreported exception error FileNotFoundException; It must be caught or declared to throw FileInputStream inputStream =new FileInputStream("/");
                                      ^
1A mistakeCopy the code

Catch the use of

Going back to catch syntax, ExceptionType corresponds to the Exception class in the Java Exception architecture or a subclass of it.

Name is the name given to the exception type, and the curly braces are the code that is executed when the exception handler is called, where the code can refer to the exception by name.

When an exception occurs in the call stack, the run-time system will call the exception handler. When the ExceptionType of the exception handler matches the type that causes the exception, that is, when a catch block is hit, the exception object will be assigned to the parameter of the exception handler, and then the exception handling code of the catch block will be executed.

Exception handlers We can do many things, such as printing error logs, suspending programs, performing error recovery, prompting users, or passing exceptions up the chain. Here is an example code for printing an error message:

public static void main(String[] args) {

    try {

        int[] arrry = {0.1.2};

        / / here will throw Java. Lang. ArrayIndexOutOfBoundsException, should not appear arrry [3] this code
        System.out.println(arrry[3]);

    } catch (IndexOutOfBoundsException e) {

        System.out.println("Array out-of-bounds exception caught:"); System.out.println(e); }}Copy the code

The output is:

Catch exceptions to the array bounds: Java. Lang. ArrayIndexOutOfBoundsException:3
Copy the code

In some scenarios, one piece of code may raise multiple exceptions, and the processing of exceptions will be relatively consistent, such as printing logs. In this case, if a separate catch block is set and the same code is written, the repetition degree will be very high.

So after Java 7, a catch block supports handling multiple types of exceptions. The syntax is as follows:

try {
    // Code that may throw an exception
} catch (ExceptionType1 name1 | ExceptionType2 name2) {
    Exception handling code for ExceptionType1 ExceptionType1 or ExceptionType2 ExceptionType2
} 

Copy the code

Using finally

Programs sometimes open resources, such as files, connections, threads, etc., while running. If an exception is thrown midway through the program, the program terminates and opened resources are never released, leading to resource leaks and even system crashes.

For example, before the program runs, I want to output a summary log for monitoring, but if an exception is thrown and the program terminates, the log will not be printed and I will not see the information I want.

Therefore, there is a need to have a mechanism to release open resources or execute specified logic if an exception occurs that blocks the process.

Java uses finally for this purpose. Finally can form either a try-finally structure or a try-catch-finally structure. But the finally block is always executed when a try exits.

This “always” can be divided into the following cases:

There is no abnormal

After the try completes without exception, the finally block is executed in the same order as a normal program.

public static void main(String[] args) {

    System.out.println("main:" + fetchMyName());

}

public static String fetchMyName(a) {

    String me = "woniu";

    try {
        me = "woniu666";

    } finally {
        System.out.println("finally: " + me);
    }

    return me;
}
Copy the code

Output:

finally: woniu666
main:woniu666
Copy the code

An exception was not caught

If an exception occurs during a try execution, the exception object is thrown, but the finally block is still executed.

public static void main(String[] args) {

    System.out.println("main:" + fetchMyName());

}

public static String fetchMyName(a) {

    String me = "woniu";
    int[] arrry = {0.1.2};

    try {
        me = "woniu666";

        / / here will throw Java. Lang. ArrayIndexOutOfBoundsException, should not appear arrry [3] this code
        System.out.println(arrry[3]);

    } finally {
        System.out.println("finally: " + me);
    }

    return me;
}
Copy the code

FetchMyName () fetchMyName() does not catch an exception and throws it up, but the logic in finally is executed first. The main method also does not catch an exception, so it blocks the program and prints the call stack.

finally: woniu666
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
	at com.springtest.demo.TryFinally.fetchMyName(TryFinally.java:28)
	at com.springtest.demo.TryFinally.main(TryFinally.java:15)
Copy the code

There are exceptions and there are catches

When an exception occurs during a try execution, the exception object is thrown, and the catch catches the exception and processes it normally. Finally code blocks are still executed.

public static void main(String[] args) {

    System.out.println("main:" + fetchMyName());

}

public static String fetchMyName(a) {

    String me = "woniu";
    int[] arrry = {0.1.2};

    try {
        me = "woniu666";

        / / here will throw Java. Lang. ArrayIndexOutOfBoundsException, should not appear arrry [3] this code
        System.out.println(arrry[3]);

    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Processor that hits an out-of-bounds exception with array index:" + e.getMessage());

    } finally {
        System.out.println("finally: " + me);
    }

    return me;
}
Copy the code

The code works fine, executing the logic in the catch block, then the finally block, and finally the main method.

The processor that hits an out-of-bounds exception with an array index is:3
finally: woniu666
main:woniu666
Copy the code

The try of the return

Return means that the method is finished, and finally is executed when a try exits. Will the finally block be executed if a try block contains a return?

Try adding a return to the try block!

public static void main(String[] args) {

    System.out.println("main:" + fetchMyName());

}

public static String fetchMyName(a) {

    String me = "woniu";
    int[] arrry = {0.1.2};

    try {
        me = "woniu666";

        // no exception is thrown here
        System.out.println(arrry[0]);

        return "try";

    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Processor that hits an out-of-bounds exception with array index:" + e.getMessage());

    } finally {
        System.out.println("finally: " + me);
    }

    return me;
}
Copy the code

The result will still be the execution of the finally code block!

0
finally: woniu666
main:try
Copy the code

The catch of the return

We tried a return ina try, but what about an execution of a return, finally ina catch?

public static void main(String[] args) {

    System.out.println("main:" + fetchMyName());

}

public static String fetchMyName(a) {

    String me = "woniu";
    int[] arrry = {0.1.2};

    try {
        me = "woniu666";

        / / here will throw Java. Lang. ArrayIndexOutOfBoundsException, should not appear arrry [3] this code
        System.out.println(arrry[3]);

    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Processor that hits an out-of-bounds exception with array index:" + e.getMessage());

        return "catch";

    } finally {
        System.out.println("finally: " + me);
    }

    return me;
}
Copy the code

The result will still be the execution of the finally code block!

The processor that hits an out-of-bounds exception with an array index is:3
finally: woniu666
main:catch
Copy the code

How do I specify exceptions thrown by a method

Now that I’m done with exception catching, I imagine a situation where my current method throws an exception, but the current method is not the right one to handle that exception, and the method higher up the call stack is better. It would be better if the current method did not catch the exception and allowed methods higher up the call stack to handle it.

At this point, if the exception thrown is a check exception, you must specify in the method that it can throw those exceptions. You need to add a throws statement to the method declaration. The THROWS statement contains the THROWS keyword, followed by all exceptions thrown by method one, separated by commas. Throws statements are placed after the method name and parameter list and before the parentheses that define the scope of the method.

A code example is as follows:

public static void test(a) throws FileNotFoundException {

    FileInputStream inputStream = new FileInputStream("/");

}
Copy the code

Handled by the upper main method:

public static void main(String[] args) {

    try {
        test();

    } catch (FileNotFoundException e) {

        System.out.println("File not found exception:"+ e.getMessage()); }}Copy the code

Normal output:

Error: / (Is a directory)Copy the code

Check exceptions must be handled because not handling will compile and fail, either by catching and handling exceptions or by specifying exceptions thrown by methods.

Is there a requirement for non-checking exceptions, namely runtime exceptions?

Non-checking exceptions are not mandatory. You can specify an exception thrown by a method or not. If you do not specify an exception, the exception object will continue to be thrown up the call stack until it is caught and handled or the program terminates.

summary

This article introduces the concept of exceptions, we understand the terms related to exceptions, the background of the occurrence of exceptions and the operation mechanism of exceptions, then we according to the Java programming specification respectively introduced how to capture exceptions and how to specify exceptions, but also introduced the Inheritance system of Java exceptions. These are very basic things, but they are very important to consider when you write code, and you can even argue that exception-oriented programming is a test of your coding skills.

I am a snail, in the Internet and you crawl together. See you next time!