Usually a program will follow the code, but sometimes an exception occurs, such as a program that keeps writing data to disk when the disk space is full. If you want to make your code more robust, you need to handle this exception. Java provides an exception handling mechanism that captures processing.

Java exception class

In Java, exception objects are derived from the Throwable class. Below is a diagram of a Java exception class.

You can see that all exceptions in Java inherit fromThrowable.ThrowableThere are two directly derived classesErrorandException.

ErrorandException

  • Error

Error describes internal errors and resource exhaustion errors in the Java runtime system, and applications should not throw objects of this type. It is thrown by the Java virtual machine.

  • Exception

Exceptions are the exceptions that the application needs to catch and handle.

Checked and unchecked types

Exception is derived from exceptions such as RuntimeException and IOException. RuntimeException is a non-checked exception that cannot be checked at compile time. An explicit catch is usually not required. RuntimeException is caused by a program error. A RuntimeException is a sign that the code is buggy and should not be caught, but fixed. Such as NullPointerException, IndexOutOfBoundsException, etc. Note: Exceptions that do not pass the pre-check are not included in this column, such as NumberFormatException, which may exist when parsing strings of numbers, even though it is a RuntimeException.

String str = "12a";
try {
    Integer.parseInt(str);
} catch (NumberFormatException e) {
    e.printStackTrace();
}
Copy the code
  • By checked exception

Exceptions other than RuntimeException are called checked exceptions, such as IOException. For a checked exception, the method either catches and handles it or throws it in the method signature.

  • Custom exception classes

It is also possible to customize exception classes in Java by inheriting existing ones. Custom Exception classes are typically implemented by inheriting a subclass of Exception. In Web development, it is common to customize some business exceptions, such as insufficient balance, repeated commits, etc. To customize an exception, you need to provide multiple constructors, such as:

public class ApiException extends RuntimeException {
    private IErrorCode errorCode;

    public ApiException(IErrorCode errorCode) {
        super(errorCode.getMessage());
        this.errorCode = errorCode;
    }

    
    public ApiException(String message) {
        super(message);
    }

    public ApiException(Throwable cause) {
        super(cause);
    }

    public ApiException(String message, Throwable cause) {
        super(message, cause);
    }

    protected ApiException(String message, Throwable cause,
                               boolean enableSuppression,
                               boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
    
    public IErrorCode getErrorCode(a) {
        returnerrorCode; }}Copy the code

The keyword associated with the exception

Exception keywords: try catch finally throws throw basic syntax:

try {
    // Possible exception code
} catch (Exception e) {
    // Exception handling code
} finally{}Copy the code

A try block can be followed by more than one catch statement associated with it, in which case the specific exception comes first and the general-purpose exception comes after. When there are multiple catch statements, the JVM matches the exception objects in sequence, and no subsequent catch blocks are executed. The finally statement block will be executed no matter what exception occurs. Throw is used to throw an exception. Throws declaration Is used in method signatures to declare exceptions that a method may throw.

try-with-resources

Before Java7, finally statements were commonly used to close file descriptors, database connections, and other resource operations. Such as:

public static void main(String[] args) {
    BufferedReader br = null;
    String line;
    try {        
        br = new BufferedReader(new FileReader("d:\\FILEPATH"));
        while((line = br.readLine()) ! =null) { System.out.println(line); }}catch (IOException e) {
        
    } finally {
        try {
            if(br ! =null) { br.close(); }}catch (IOException ex) {
            
        }
    }
}
Copy the code

Starting with Java7, the JDK provides try-with-resources to close a resource. The above example can be rewritten as follows:

public static void main(String[] args) {   
    String line;
    try (BufferedReader br = new BufferedReader(new FileReader("d:\\FILEPATH"))) {while((line = br.readLine()) ! =null) { System.out.println(line); }}catch (IOException e) {
    } 
}
Copy the code

After the rewrite of the code, much more concise than the previous code. Therefore, it is recommended to close resources in this way.

Handle exceptions correctly

Some bad examples:

Example 1

try {
    // TODO RPC remote call
} catch (Exception e) {
    log.error("fail", e);
}
Copy the code

In RPC calls, in the case of high concurrency, RPC may time out, which results in log.error() printing more frequently, and log.error() printing all stack information of calls, occupying more I/O resources and reducing program performance. The correct way to do this is to print only error information, not stack information. to

try {
    // TODO RPC remote call
} catch (Exception e) {
    log.error("fail", e.getMessage());
}
Copy the code

Example 2

try {
    // TODO RPC remote call
    log.info("rpc response {}", JSON.toJSONString(rpcResponseDate));
} catch (Exception e) {
    log.error("fail", e);
}
Copy the code

When the JSON tool is used to convert an object into a String, if some GET methods in the object are overwritten and exceptions are thrown, normal business processes may be affected due to log printing.

Example 3

try {
    // TODO mysql success
    // TODO deal mysql response date
    
} catch (Exception e) {
    log.error("fail", e.getMessage());
}
Copy the code

In the operation of the MySQL database, if an exception occurs, you need to handle the exception according to the specific service logic rather than just printing the error information. Alibaba Java development manual is mandatory to this point.

  1. [Mandatory] If you need to roll back a transaction after a catch exception occurs, manually roll back the transaction.

Finally and return execution order

If there is a return statement inside try(), will the code in finally be executed and when, before or after the return? If there is a return in the try block, the code in the finally block will still execute, so the statement in finally will execute before the return. What would be the output of the following code?

public class Test {

    private static final Logger LOGGER = LoggerFactory.getLogger(Test.class);

    static class MyInteger {
        int i;
    }

    public static int test1(a) {
        int i = 0;

        try {
            i++;
            return i;
        } catch (Exception e) {
            // There is no point in catching exceptions here, just for testing
        } finally {
            i++;
        }

        return i;
    }

    public static int test2(a) {
        int i = 0;
        try {
            i++;
            return i;
        } catch (Exception e) {
            // There is no point in catching exceptions here, just for testing
        } finally {
            i++;
            returni; }}public static MyInteger test3(a) {
        MyInteger myInteger = new MyInteger();
        try {
            myInteger.i++;
            return myInteger;
        } catch (Exception e) {
            // There is no point in catching exceptions here, just for testing
        } finally {
            myInteger.i++;
        }
        return myInteger;
    }

    public static void main(String[] args) {
        int result1 = test1();
        LOGGER.info("test1 result: " + result1);

        int result2 = test2();
        LOGGER.info("test2 result: " + result2);

        int result3 = test3().i;
        LOGGER.info("test3 result: "+ result3); }}Copy the code

Run the code, and the output is 1, 2, 2. In test1(), the return in the try pushes the value 1 onto the function stack frame, and then executes finally. Although finally changes the value of I to 2, the value on the function stack frame does not change, so the final result is 1. In test2(), the return in the try pushes 1 onto the function stack frame, then executes finally, finally changes I to 2, and then returns pushes 2 onto the function stack frame, so the result is 2. Test3 () returns a reference type. For the reference type try, the return pushes the address of the reference type onto the stack frame. Finally, finally changes the property I of the object to 2 by the address.

The log specification

Reference: Alibaba Java Development Manual 1.4.0