Java Exception Handling and design, Java Exception Handling Design

Source: Internet
Author: User

Java Exception Handling and design, Java Exception Handling Design

Notes for learning Java !!! If you have any questions or want to obtain learning resources during the learning process, join the Java learning exchange group with the group number 618528494.Let's learn Java together!

In programming, exception handling is a key and important part. The exception handling framework of a program directly affects the code quality of the entire project, as well as the maintenance cost and difficulty. Imagine if a project has not considered Exception Handling from start to end, where can the program find the root cause of the error? However, if a project has too many Exception Handling designs, it will seriously affect the code quality and program performance. Therefore, it is an art to design Exception Handling efficiently and concisely. This article first describes the basic knowledge of Java exception mechanism, and then provides several suggestions for Java Exception Handling design.

If any error occurs, please forgive me and correct me. Thank you very much.

The following is the directory outline of this article:

1. What is an exception?
Ii. How to handle exceptions in Java
3. deep understanding of the five keywords "try", "catch", "finally", "throws", and "throw"
4. How to throw an exception during method override during class inheritance
5. Suggestions on Exception Handling and Design

1. What is an exception?

The English word for an exception is exception. The Literal Translation Means "accident, exception", that is, an abnormal situation. In fact, exceptions are essentially program errors, including program logic errors and system errors. For example, the use of null references, array subscript out-of-bounds, memory overflow errors, and so on are all unexpected situations that deviate from our program's intention. Errors often occur during programming, including errors during compilation and runtime. errors during compilation can be corrected by the compiler, however, errors during runtime are not as good as the compiler can, and errors during runtime are often unpredictable. If an error occurs during the running of the program, the program will terminate or directly cause the system to crash if it is ignored. Obviously this is not the expected result. Therefore, how can we handle and remedy errors during operation? Java provides an exception mechanism to handle errors during program running. Through the exception mechanism, we can better improve program robustness.

Exceptions are processed as objects in Java. The root class is java. lang. the Throwable class defines many Exception classes in Java (such as OutOfMemoryError, NullPointerException, and IndexOutOfBoundsException). These Exception classes are divided into two categories: Error and Exception.

Error is an exception that cannot be handled, such as OutOfMemoryError. Generally, if this exception occurs, the JVM will terminate the program. Therefore, we do not need to care about such exceptions when writing programs.

Exceptions, that is, exceptions we often see, such as NullPointerException and IndexOutOfBoundsException. These exceptions can be handled.

Exceptions of the Exception class include checked exception and unchecked exception (unchecked exception is also called RuntimeException. Of course, the Exception here is not an exception during the running as I mentioned earlier, in Java, the term runtime Exception is used to indicate that exceptions of the Exception class occur during runtime ).

Unchecked exception (non-check exception), also known as RuntimeException, such as common NullPointerException and IndexOutOfBoundsException. For runtime exceptions, the java compiler does not require exception capture and processing or throw a declaration, which is determined by the programmer.

Checked exception (check exception), also known as non-runtime exception (Exceptions other than runtime exceptions are non-runtime exceptions), the java compiler forces programmers to capture and handle, for example, common IOExeption and SQLException. If non-runtime exceptions are not captured or declared, compilation fails.

Shows the structure hierarchy of exception classes in Java:


In Java, the parent class of all Exception classes is the Throwable class, the Error class is the parent class of the error Type exception, and the Exception class is the parent class of the exception type Exception, the RuntimeException class is the parent class of all runtime exceptions. classes other than RuntimeException that inherit Exception are non-runtime exceptions.

Typical RuntimeException include NullPointerException, IndexOutOfBoundsException, and IllegalArgumentException.

Typical non-RuntimeException types include IOException and SQLException.

Ii. How to handle exceptions in Java

To handle exceptions in Java, you must first capture the exceptions and then process them. How can I capture and Process Code that may encounter exceptions? Use the try and catch keywords, as shown in the following code:

try {
  File file = new File("d:/a.txt");
  if(!file.exists())
    file.createNewFile();
} catch (IOException e) {
  // TODO: handle exception
}

The Code enclosed by the try block indicates that this part of the Code may have an exception. Once an exception occurs, the exception will be caught by the catch, and then the exception must be handled in the catch Block.

This is a way to handle exceptions. In Java, another exception handling method is provided, that is, throwing an exception. As the name suggests, in the event of an exception, I throw it and ask the caller to handle it, if you do not perform specific processing, you need to use the throw and throws keywords.

The following is an example:

public class Main {
    public static void main(String[] args) {
        try {
            createFile();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
     
    public static void createFile() throws IOException{
        File file = new File("d:/a.txt");
        if(!file.exists())
            file.createNewFile();
    }
}

The difference between this code and the above Code is that in the actual createFile method, no exception is caught, but an exception is thrown with the throws keyword declaration, that is, inform the caller of this method that this method may throw an IOException. When the createFile method is called in the main method, try... catch Block is used for exception capture.

Of course, you can also use the throw keyword to manually throw an exception object. The following is an example:

public class Main {
    public static void main(String[] args) {
        try {
            int[] data = new int[]{1,2,3};
            System.out.println(getDataByIndex(-1,data));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
         
    }
     
    public static int getDataByIndex(int index,int[] data) {
        if(index<0||index>=data.length)
            throw new ArrayIndexOutOfBoundsException("数组下标越界");
        return data[index];
    }
}

Then, capture in the catch Block.

In other words, if you handle exceptions in Java, you can select three methods for exception handling for code that may encounter exceptions:

1) Use try .. catch to capture and process code blocks;

2) throws are used to throw a declaration in the method of this Code in vitro, informing the caller of this method that this Code may encounter these exceptions, and you need to handle them with caution. There are two situations:

If the declared exception is a non-runtime exception, the caller of this method must use the try... catch Block to capture the exception or continue to throw the exception to the upper layer.

If the declared exception is a runtime exception, the caller of this method can selectively capture and handle the exception.

3) throw an exception object with throw in the code block. There are two cases, which are similar to those in section 2:

If the thrown exception object is a non-runtime exception, the caller of this method must capture the object explicitly using try... catch Block or continue to throw an exception to the upper layer.

If the thrown exception object is a runtime exception, the caller of this method can selectively capture and handle the exception.

(If an exception is finally thrown to the main method, it is equivalent to giving it to the jvm for automatic processing. At this time, the jvm will simply print the exception information)

3. deep understanding of the five keywords "try", "catch", "finally", "throws", and "throw"

Next, let's take a look at the usage of the five keywords in the exception mechanism and what you need to pay attention.

1. try, catch, finally

The try keyword is used to enclose the logic code that may encounter exceptions. It cannot be used independently and must be used with catch or finally. Java compilers allow the following three forms of combination:

Try... catch...; try... finally...; try... catch... finally...

Of course, there can be multiple catch blocks. Note that there can only be one try block, and the finally block is optional (but there can only be one finally block at most ).

The execution sequence of the three blocks is try-> catch-> finally.

Of course, if no exception occurs, the catch block will not be executed. However, the finally block will be executed under any circumstances (this is important, so in some cases, the resource release operation will be carried out in the finally block ).

When multiple catch blocks exist, they are matched in the order of catch blocks. Once the exception type is matched by a catch block, it will not match the catch Block.

When using try... catch... finally blocks, be sure not to use return in the finally blocks, because the return in finally overwrites the existing return values. The following is an example:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
 
 
public class Main {
    public static void main(String[] args) {
        String str = new Main().openFile();
        System.out.println(str);
         
    }
     
    public String openFile() {
        try {
            FileInputStream inputStream = new FileInputStream("d:/a.txt");
            int ch = inputStream.read();
            System.out.println("aaa");
            return "step1";
        } catch (FileNotFoundException e) {
            System.out.println("file not found");
            return "step2";
        }catch (IOException e) {
            System.out.println("io exception");
            return "step3";
        }finally{
            System.out.println("finally block");
            //return "finally";
        }
    }
}

The output result of this program is:

It can be seen that after FileNotFoundException occurs in the try block, the system jumps to the first catch Block, prints the "file not found" information, assigns "step2" to the returned value, and then executes the finally block, finally, return the returned value.

From this example, the finally block is executed no matter whether the try block or catch block contains the return statement.

If you modify the program a little, remove the comments of the return Statement in the finally block. The running result is:


Finally is printed, and the returned value is overwritten.

Therefore, if the method has a return value, do not use return in finally. This will make the program structure messy.

2. throws and thow keywords

1) throws appears in the method declaration, indicating that the method may throw an exception, and then sends it to the upper-layer method program for processing, allowing throws to follow multiple exception types;

2) It is generally used when a program encounters a logic and the programmer throws a specific type of exception. Throw only appears in the method body. When a method encounters an exception during execution, it encapsulates the exception information as an exception object and throw it out. A very important role of the throw keyword is the conversion of exception types (will be explained later ).

Throws indicates the possibility of exceptions. throw throws throw an exception and throw an exception object. Both of them are passive Exception Handling Methods (here the negative is not to say that this method is not good), but it only throws or may throw an exception, but it is not handled by methods, handle exceptions by calling the upper layer of the method.

4. How to throw an exception during method override during class inheritance

This section describes how to determine the type of the thrown declaration when a subclass overrides the parent class method. The following are three principles:

1) The method of the parent class does not declare an exception, and the subclass cannot declare an exception when rewriting the method;

2) If the method of the parent class declares an exception exception1, the exception declared by the subclass when the method is rewritten cannot be the parent class of exception1;

3) if the exception type declared by the method of the parent class is only non-runtime exception (runtime exception ), when the subclass overrides this method, the declared exceptions can only be non-runtime exceptions (runtime exceptions), and cannot contain runtime exceptions (non-runtime exceptions ).


5. Suggestions on Exception Handling and Design

The following are some suggestions for Exception Handling Based on previous summaries:

1. Use exceptions only when exceptions are necessary. Do not use exceptions to control program processes.

Exercise caution when using exceptions. Exception capture is costly. Excessive exceptions may seriously affect program performance. If the program can use the if statement and Boolean variable for logical judgment, the use of exceptions should be minimized to avoid unnecessary exception capture and processing. For example, the following typical program:

public void useExceptionsForFlowControl() {  
  try {  
  while (true) {  
    increaseCount();  
    }  
  } catch (MaximumCountReachedException ex) {  
  }  
  //Continue execution  
}  
    
public void increaseCount() throws MaximumCountReachedException {  
  if (count >= 5000)  
    throw new MaximumCountReachedException();  
}

The preceding useExceptionsForFlowControl () uses an infinite loop to increase the count until an exception is thrown. This does not mean that the Code is not easy to read, but reduces the execution efficiency of the program.

2. Do not use empty catch blocks.

When an exception is caught, nothing is done, which is equivalent to ignoring this exception. Do not use empty catch blocks. Empty catch blocks mean that errors and exceptions are hidden in the program, and may cause uncontrollable execution results. If you are sure that the caught exception will not affect the program in any way, you 'd better use the Log to record the exception so that it can be easily updated and maintained in the future.

3. Check exceptions and non-check exceptions

Once you decide to throw an exception, you need to decide what exception to throw. The main problem here is whether to throw a check exception or not.

Check exceptions cause too many try... Catch code, there may be a lot of check exceptions that developers cannot reasonably handle, such as SQLException, but developers have to try... Catch, which will lead to the frequent occurrence of such a situation: there are only a few lines of logic code, but there are many lines of code for exception capture and processing. This not only makes the logic code obscure, but also reduces the performance of the program.

I personally recommend that you try to avoid exceptions. If this exception is common and the caller needs to be reminded to handle the exception, check the exception; otherwise, use non-check exceptions.

Therefore, in general, I think we should try to convert the check exceptions to non-check exceptions and hand them over to the upper layer for handling.

4. Pay attention to the catch Block sequence.

Do not place exceptions of upper classes in the catch block at the beginning. For example, the following code:

try {
        FileInputStream inputStream = new FileInputStream("d:/a.txt");
        int ch = inputStream.read();
        System.out.println("aaa");
        return "step1";
    } catch (IOException e) {
        System.out.println("io exception");        
         return "step2";
    }catch (FileNotFoundException e) {
        System.out.println("file not found");          
        return "step3";
    }finally{
        System.out.println("finally block");
        //return "finally";
    }

The FileNotFoundException of the second catch will never be captured, because FileNotFoundException is a subclass of IOException.

5. Do not include the information provided to the user in the exception information.

For example, the following code:

public class Main {
    public static void main(String[] args) {
        try {
            String user = null;
            String pwd = null;
            login(user,pwd);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
         
    }
     
    public static void login(String user,String pwd) {
        if(user==null||pwd==null)
            throw new NullPointerException("用户名或者密码为空");
        //...
    }
}

It is recommended that you do not confuse the error prompt information with the program. A better way is to put all the error prompt information in a configuration file for unified management.

6. Avoid recording the same exception multiple times in the log information.

Logs are recorded only at the beginning of an exception. In many cases, exceptions run upwards. If they are all logged to the Log system every time they are thrown up, the root cause of the exception cannot be found.

7. handle exceptions at a higher level.

The exception should be thrown to the upper-layer callers as much as possible. How can this problem be handled when the upper-layer callers are unified. If an exception occurs in each place, the program exception handling process is disordered, which is not conducive to subsequent maintenance and troubleshooting. The unified processing by the upper layer will make the entire process clear and easy to understand.

8. release resources in finally

If you use File Reading, network operations, and database operations, remember to release resources in finally. This will not only make the program occupy less resources, but also avoid unnecessary exceptions due to the unreleased resources.

Notes for learning Java !!!

If you have any questions or want to obtain learning resources during the learning process, join the Java learning exchange group with the group number 618528494.Let's learn Java together!


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.