头图
Author of this article: Yihen

Basic knowledge

Java exception

Exception hierarchy

In Java, there are two types of exceptions: Checked Exception and Unchecked Exception . The red portion of the lower figure shows Unchecked Exception abnormality, Blue shows Checked Exception . The structure diagram is as follows:

image

Checked Exception

Checked Exception must be explicitly captured or passed, otherwise an error will be displayed during compile time.
Generally speaking, Checked Exception refers to errors that are not directly controlled by the program. They usually occur due to interaction with external resources and the network, such as database problems, network connection errors, file loss and other issues.

Checked Exception often a subclass of the Exception class.

Checked Exception are: ClassNotFoundException , IOException , SQLException etc.

Unchecked Exception

Unchecked Exception is the capture or transfer that the developer does not need to display, and no error will be reported at compile time.

The compiler will not force the Unchecked Exception to capture the display of 06116380bc3d43.

Unchecked Exception

  1. RuntimeException . Eg: NullPointerException , AritheticException , ArrayStoreException , ClassCastException etc.
  2. Error . eg: StackOverflowError , OutOfMemoryError etc.

Kotlin exception

All exception classes in Kotlin are descendants of the Throwable class, which is similar to Java, but there is no Checked Exception in Kotlin, so all Exceptions in Kotlin are Unchecked Exception , which means that the compiler will not force any exceptions to be caught.

background

  • Question 1: Under what circumstances is it suitable to throw an exception?

Usually when you are developing, there will be some exceptions that will be thrown directly when the execution logic or the parameters do not meet expectations. The following code is more common:

public boolean open(xxx) {
    if (xxx) {
        xxxx
    } else {
        throw new IllegalArgumentException("xxxx");
    }
    return xxxx;
}

If the code execution matches the exception logic and the caller fails to catch the corresponding exception at runtime, the application will crash directly, causing an unfriendly experience to the user.

  • Question 2: How should the code for catching exceptions be written?

In our usual development, how should we write normatively for scenes that need to catch exceptions? For example, is the following code reasonable?

try {
    xxxx
} catch (Throwable e) {
    e.printStackTrace();
}
  • Question 3: The mixed development of Kotlin and Java
    Java and Kotlin have different design concepts for exceptions, so how to align the differences between the two during intermodulation? The biggest difference is that Kotlin does not have Checked Exception , so there will be some controversial issues when the project uses Kotlin and Java mixed development:

    • Catch exception controversy

    When Kotlin calls Java code, if Java throws Checked Exception , should Kotlin actively catch it or not? Our first reaction is to capture, since we want to capture, but during the development stage, ide will not give a display prompt, and it will not report an error at compile time if it is not captured.

    • Throw an exception

    How should Kotlin write scenarios where exceptions need to be thrown? Just throw the exception? If it is thrown, it is difficult for the caller to perceive the exception, so there is a risk of the code hitting the related exception and crashing.

Due to the existence of the above various problems, in the case that all developers at the cognitive level have not reached an agreement, there will also be inconsistent standards during code review. Irregular use of abnormalities will also lead to more online crashes, and the industry also There is no set of more feasible standards that can be used directly, so we have to formulate a set of effective rules and procedures to solve these problems.

Solution

Regarding the inconsistency between Java and Kotlin exceptions, we chose to align the Java code specifications based on code quality considerations, so on the Kotlin side we define similar `
The concept of Checked Exception`, for the ability to display prompts, is realized with the help of Lint's ability (the Kotlin compiler will not force any exceptions to be caught).

For throwing exceptions, it is clearly stipulated that upper-level business callers are not allowed to throw exceptions. Only API providers are allowed to throw exceptions when they have to throw exceptions, and Checked Exception must be thrown.

For catching exceptions, in principle, catching is to handle it, and necessary processing logic should be added. In scenarios where the catching is only for the bottom of the picture (a crash may occur), a tool class for reporting exceptions should be provided. Other usage rules align with industry standards.

Finally, for all the established rules, Lint detection capability is provided, and card points are performed in the MR process to ensure the correctness of the code.

Next, I will introduce Xiayun Music's unusual usage specifications for Java and Kotlin.

specification

Java specification

Throw Exception

  1. The caller at the top level avoids throwing exceptions;

    Note: If the caller at the top level throws an exception, in the case of a logical hit, the app will crash directly;

  2. For scenes that need to throw exceptions, avoid directly throwing Unchecked Exception (RuntimeException subclass, users cannot display perception, no capture processing, prone to crashing), and it is not allowed to throw Exception or Throwable directly; the thrown exception should be inherited Exception, that is, Checked Exception (the user can display the perception, you can deal with it), you should use a custom exception with business meaning. Recommend custom exceptions that have been defined in the industry, such as DAOException, ServiceException, etc.;
  3. Throw a more specific exception;

    Explanation: The more specific and specific the exception you throw, the better. Users can take different remedial measures according to specific abnormalities. Therefore, you need to make sure to provide as much information as possible, which will make your API easier to understand.

Catch exception (try catch)

  1. The purpose of catching an exception is to handle it. Don’t catch it but discard it without handling it. If you don’t want to handle it, please
    Throw the exception to its caller. The outermost business users must deal with exceptions and turn them into something that users can understand
    content. In some trapping logic, relevant exception information needs to be reported.

    The reporting interface is as follows ( Monitor category):

    /**
     * 上报日志信息到异常监控平台
     */
     void logActiveReport(Throwable throwable);

    eg:

    try {
        xxxxs
    } catch (IOException e) {
        // 上报后可在异常平台上查询到相关信息
        ServiceFacade.get(Monitor::class.java).logActiveReport(...)
    }
  2. catch , please distinguish stable code and non-stable code, stable code refers to the code that will not go wrong anyway.
    For the non-stable code catch try to distinguish the exception types as much as possible, and then do the corresponding exception handling.

    Explanation: Try-catch a large section of code, so that the program cannot make correct stress responses based on different abnormalities, and it is not conducive to positioning the problem. This is an irresponsible performance.

    Positive example: In the user registration scenario, if the user enters illegal characters, or the user name already exists, or the user enters the password too much
    Simple, make a classification judgment on the program and prompt the user.

  3. Do not use return finally block.

    Note: After the return in the finally block returns, the method ends, and the result of the return statement in the try block will not be returned, that is, the return value is overwritten by the return value of the finally;

  4. try catch only handles exceptions that the application can handle. Do not catch Throwable .

    Explanation: Throwable is the parent of all Exceptions and Errors If you use Throwable catch clause, it will not only catch all exceptions, but also all errors. These errors are JVM to indicate serious errors that are not intended to be handled by the application. OutOfMemoryError and StackOverflowError are typical examples. Both of these situations are caused by situations beyond the control range of the application and cannot be handled.

    Error case:

    try {
        xxxxs
    } catch (Throwable e) {
        e.printStackTrace();
    }

Kotlin specification

Throw Exception

  1. Try to avoid throwing exceptions in Kotlin code, especially the top caller;

    Note: If the caller at the top level throws an exception, the app will crash directly in the event of a logical hit;

  2. For scenarios that need to throw an exception, when the exception is thrown in the code, it needs to be thrown in the method declaration (similar to the practice of Checked Exception Recommend custom exceptions that have been defined in the industry, such as DAOException, ServiceException, etc.;
    Correct way:

    // 显示的抛出来
    @Throws(IOException::class)
    fun xxxx() {
        throw IOException("xxxx")
    }
  3. Throw a more specific exception;

    Explanation: The more specific and specific the exception you throw, the better. Users can take different remedial measures according to specific abnormalities. Therefore, you need to make sure to provide as much information as possible, which will make your API easier to understand.

Catch exception (try catch)

  1. For the exceptions thrown by the code display (Java Checked Exception and Kotlin displayed exceptions), the corresponding capture should be carried out.
  2. The purpose of catching an exception is to handle it. Don’t catch it but discard it without handling it. If you don’t want to handle it, please
    Throw the exception to its caller. The outermost business users must deal with exceptions and turn them into something that users can understand
    content. In some trapping logic, relevant exception information needs to be reported.

    The reporting interface is as follows ( Monitor category):

    /**
     * 上报日志信息到异常平台
     */
     void logActiveReport(Throwable throwable);
  3. catch , please distinguish stable code and non-stable code, stable code refers to the code that will not go wrong anyway.
    For the non-stable code catch try to distinguish the exception types as much as possible, and then do the corresponding exception handling.

    Explanation: Try-catch a large section of code, so that the program cannot make correct stress response according to different abnormalities, and it is not conducive to positioning the problem. This is an irresponsible performance.

    Positive example: In the user registration scenario, if the user enters illegal characters, or the user name already exists, or the user enters the password too much
    Simple, make a classification judgment on the program and prompt the user.

  4. Do not use return finally block.

    Note: After the return in the finally block returns, the method ends, and the result of the return statement in the try block will not be returned, that is, the return value is overwritten by the return value of the finally;

    Summarize

  5. Compared with the industry's related code specifications for Java and Kotlin, we will define more stringent specifications. The industry specifications are basically a guide to the use of code, and the code specifications we define are more code writing guidelines from the perspective of ensuring app quality. .
  6. At present, the industry Checked Exception has not ceased. The Kotlin author's view is that Checked Exception not have appeared, but Checked Exception does have a certain value for our code quality assurance. This article does not discuss this point of view. We chose Kotlin to align Checked Exception because of the unification of Java and Kotlin's exception specifications and the improvement of the quality of the app.
  7. For the crash problem caused by the irregular use of the code, our approach is basically to formulate a standard and add the corresponding Lint to solve the corresponding problem. Kotlin-related code specifications currently do not have a set of authoritative specifications in the industry, so when you use Kotlin, you need to pay more attention to the quality problems caused by some potential code problems.

    Reference

  8. Checked or Unchecked Exceptions?
  9. Kotlin Exceptions
  10. Alibaba Java Development Manual
  11. Java's checked exceptions were a mistake
  12. The Trouble with Checked Exceptions
This article is published from big front-end team of NetEase Cloud Music . Any form of reprinting of the article is prohibited without authorization. We recruit front-end, iOS, and Android all year round. If you are ready to change jobs and you happen to like cloud music, then join us at grp.music-fe(at)corp.netease.com!

云音乐技术团队
3.6k 声望3.5k 粉丝

网易云音乐技术团队