Ten suggestions for Java exception handling

Posted by sheilam on Mon, 15 Jun 2020 18:07:36 +0200

Preface

Ten suggestions for Java exception handling, I hope to help you ~

This article has been uploaded to github:

https://github.com/whx123/Jav...

Public number: A little boy collecting snails

First, try not to use e.printStackTrace(), but to use log printing.

Counterexamples:

try{
  // do what you want  
}catch(Exception e){
  e.printStackTrace();
}

Example:

try{
  // do what you want  
}catch(Exception e){
  log.info("There's something wrong with your program,{}",e);
}

Reason:

  • Printed stack logs from printStackTrace() are interlaced with business code logs, and it is often not convenient to troubleshoot exception logs.
  • The string produced by the e.printStackTrace() statement records stack information. If the information is too long, the memory block in which the string constant pool is located has no space, that is, the memory is full, and the user's request is stuck~

2. catch exceptions, but no specific exceptions were printed out to better locate the problem

Counterexamples:

try{
  // do what you want  
}catch(Exception e){
  log.info("There's something wrong with your program");
}

Example:

try{
  // do what you want  
}catch(Exception e){
  log.info("There's something wrong with your program,{}",e);
}

Reason:

  • In the counter example, exceptions are not listed, so it will be difficult to find out the problem by then. Is it SQl Written Error or IO exception or something else?So exceptions should be printed to the log.

3. Do not use an Exception to catch all possible exceptions

Counterexamples:

public void test(){
    try{
        //...Code call throwing IOException
        //...Code call throwing SQLException
    }catch(Exception e){
        //All possible exceptions caught with base class Exception will lose valid information about the original exception if caught in this way at multiple levels
        log.info("Exception in test,exception:{}", e);
    }
}

Example:

public void test(){
    try{
        //...Code call throwing IOException
        //...Code call throwing SQLException
    }catch(IOException e){
        //Only capture IOException
        log.info("IOException in test,exception:{}", e);
    }catch(SQLException e){
        //Only capture SQLException
        log.info("SQLException in test,exception:{}", e);
    }
}

Reason:

  • All possible exceptions caught with base class Exception will lose valid information about the original exception if caught in this way at multiple levels

4. Remember to use finally to close streaming resources or try-with-resource s directly

Counterexamples:

FileInputStream fdIn = null;
try {
    fdIn = new FileInputStream(new File("/jay.txt"));
    //Turn off stream resources here?Are there any questions?What if something abnormal happens?
    fdIn.close();
} catch (FileNotFoundException e) {
    log.error(e);
} catch (IOException e) {
    log.error(e);
}

Example 1:

You need to use finally to close the stream resource as follows

FileInputStream fdIn = null;
try {
    fdIn = new FileInputStream(new File("/jay.txt"));
} catch (FileNotFoundException e) {
    log.error(e);
} catch (IOException e) {
    log.error(e);
}finally {
    try {
        if (fdIn != null) {
            fdIn.close();
        }
    } catch (IOException e) {
        log.error(e);
    }
}

Example 2:

Of course, you can also use JDK7's new feature try-with-resource, which is a new feature provided by Java7 for automatic resource management.

  • A resource is an object that must be closed after the program runs out.
  • try-with-resources ensures that each declared resource will be closed at the end of the statement
  • What kind of objects can be used as resources?As long as it is implementedJava.lang.AutoCloseableInterface orJava.io.CloseableThe object of the interface, all OK.
try (FileInputStream inputStream = new FileInputStream(new File("jay.txt")) {
    // use resources   
} catch (FileNotFoundException e) {
    log.error(e);
} catch (IOException e) {
    log.error(e);
}

Reason:

  • If you do not use finally or try-with-resource, when an exception occurs to the program and the IO resource flow is not closed, then the IO resource will be occupied by it all the time, so that no one else can use it, which causes a waste of resources.

5. Catching and throwing exceptions must exactly match, or catching exceptions must be the parent of throwing exceptions

Counterexamples:

//BizException is a subclass of Exception
public class BizException extends Exception {}
//Throw Parent Exception
public static void test() throws Exception {}

try {
    test(); //Compilation error
} catch (BizException e) { //Catching exception subclasses is not a match
    log.error(e);
}

Example:

//Throw Subclass Exception
public static void test() throws BizException {}

try {
    test();
} catch (Exception e) {
    log.error(e);
}

6. The exception caught can not be ignored, at least do some logging

Counterexamples:

public static void testIgnoreException() throws Exception {
    try {       
        // Do something
    } catch (Exception e) {     //Normally this exception will not occur
        
    }
}

Example:

public static void testIgnoreException() {
    try {
        // Do something
    } catch (Exception e) {     //Normally this exception will not occur
        log.error("This exception should not occur here,{}",e); 
    }
}

Reason:

  • Although an exception doesn't happen in normal circumstances, if you catch it, don't ignore it. At least log it.

7. Be aware of the impact of exceptions on your code hierarchy (early detection and early handling)

Counterexamples:

public UserInfo queryUserInfoByUserId(Long userid) throw SQLException {
    //Query database based on user Id
}

Example:

public UserInfo queryUserInfoByUserId(Long userid) {
    try{
        //Query database based on user Id
    }catch(SQLException e){
        log.error("Query database is abnormal.{}",e);
    }finally{
        //Close connections and clean up resources
    }
}

Reason:

  • Our projects generally have different hierarchies of code, such as Action, Service, Dao, etc. If you are an exception handled by the DAO layer, handle it as soon as possible. If you throw SQLException up, the upper code will still be handled by try catch, which will pollute your code~

8. Custom encapsulation exceptions, do not discard the original exception information Throwable cause

Often, we want to throw another exception after catching one, and we want to save the information about the original exception, which is called an exception chain.Exception chains are used when the company's framework provides uniform exception handling. We customize wrapping exceptions and don't discard information about the original exceptions, otherwise troubleshooting will be a headache

Counterexamples:

public class TestChainException {
    public void readFile() throws MyException{
        try {
            InputStream is = new FileInputStream("jay.txt");
            Scanner in = new Scanner(is);
            while (in.hasNext()) {
                System.out.println(in.next());
            }
        } catch (FileNotFoundException e) {
            //e Save exception information
            throw new MyException("Where are the files?");
        }
    }
    public void invokeReadFile() throws MyException{
        try {
            readFile();
        } catch (MyException e) {
            //e Save exception information
            throw new MyException("File not found");
        }
    }
    public static void main(String[] args) {
        TestChainException t = new TestChainException();
        try {
            t.invokeReadFile();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}
//MyException Constructor
public MyException(String message) {
        super(message);
    }

The results are as follows, without Throwable cause, it's not good to troubleshoot what's wrong

Example:


public class TestChainException {
    public void readFile() throws MyException{
        try {
            InputStream is = new FileInputStream("jay.txt");
            Scanner in = new Scanner(is);
            while (in.hasNext()) {
                System.out.println(in.next());
            }
        } catch (FileNotFoundException e) {
            //e Save exception information
            throw new MyException("Where are the files?", e);
        }
    }
    public void invokeReadFile() throws MyException{
        try {
            readFile();
        } catch (MyException e) {
            //e Save exception information
            throw new MyException("File not found", e);
        }
    }
    public static void main(String[] args) {
        TestChainException t = new TestChainException();
        try {
            t.invokeReadFile();
        } catch (MyException e) {
            e.printStackTrace();
        }
    }
}
//MyException Constructor
public MyException(String message, Throwable cause) {
        super(message, cause);
    }

9. Runtime exception RuntimeException should not be handled by catch, but pre-checked first, such as NullPointerException handling

Counterexamples:

try {
  obj.method() 
} catch (NullPointerException e) {
...
}

Example:

if (obj != null){
   ...
}

10. Attention to the order of exception matching and priority in catching specific exceptions

Note the order in which exceptions are matched, because only the first catch block that matches the exception is executed.If you want to see a NumberFormatException exception, throw a NumberFormatException, or an IllegalArgumentException if it is.

Counterexamples:

try {
    doSomething("test exception");
} catch (IllegalArgumentException e) {       
    log.error(e);
} catch (NumberFormatException e) {
    log.error(e);
}

Example:

try {
    doSomething("test exception");
} catch (NumberFormatException e) {       
    log.error(e);
} catch (IllegalArgumentException e) {
    log.error(e);
}

Reason:

  • Because NumberFormatException is a subclass of IllegalArgumentException, in the negative case, whatever exception is matched to IllegalArgumentException, it will no longer be executed down, so it is not known if it is a NumberFormatException.So you need to catch specific exceptions first, put NumberFormatException first~

Public Number

  • Welcome to pay attention to my Personal Public Number, make friends and study together.
  • If the answers are incorrectly organized, please point out Ha, thank you very much~

Topics: Java Database github SQL