Java 异常处理最佳实践

0…来源

1. 异常的分类

在这里插入图片描述

  • 非运行时异常,必须处理
  • 运行时异常,可能出现的地方也要处理

2.一般规范

  • 先讲规范,再讲实例
  • 不要在 try 中关闭资源 Example1

    在finally 中或者使用 Java8的语法糖 try(xxx){}

  • 指定具体异常,不要直接使用 Exception抛出 Example2
  • 给异常加点说明,比如说是什么执行错误 Example3
  • 使用描述性信息抛出异常 使用 log4j 记录描述信息和异常 Example4
  • 有多个异常优先捕获具体异常 Example5
  • 不要捕获 Throwable 异常,因为这个包括了 Exception 和 Error Example 6
  • 不要忽略异常 Example7
  • 不要记录了异常同时又抛出 Example8
  • 包装异常不要丢弃原始异常 Example9
  • 我的理解

    在方法内处理异常,指明具体异常以及说明
    异常记录进日志就不要抛出了?
    包装异常不要丢弃原始的异常

3.实例说明

3.1 Example1.java

public class Example1 {

    private static final Logger log = LoggerFactory.getLogger(Example1.class);
	
    public void doNotCloseResourceInTry() {
        FileInputStream inputStream = null;
        try {
            File file = new File("./王爵的私有宝贝.txt");
            inputStream = new FileInputStream(file);
            // 使用 inputStream 读取文件内容

            // 兄弟,不要这么做
            inputStream.close();
        } catch (FileNotFoundException e) {
            log.error("", e);
        } catch (IOException e) {
            log.error("", e);
        }
    }

    public void closeResourceInFinally() {
        FileInputStream inputStream = null;
        try {
            File file = new File("./王爵的私有宝贝.txt");
            inputStream = new FileInputStream(file);
            // 使用 inputStream 读取文件内容

        } catch (FileNotFoundException e) {
            log.error("", e);
        } catch (IOException e) {
            log.error("", e);
        } finally {
            if(null != inputStream){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("关闭流失败", e);
                }
            }
        }
    }

    public void autoCloseResource() {
        File file = new File("./王爵的私有宝贝.txt");
        try (FileInputStream inputStream = new FileInputStream(file)){
            // 使用 inputStream 读取文件内容

        } catch (FileNotFoundException e) {
            log.error("", e);
        } catch (IOException e) {
            log.error("", e);
        }
    }
}

3.2 Example2.java

/**
 * 指定具体异常
 *
 * @author biezhi
 * @date 2018/9/18
 */
public class Example2 {

    public void doNotDoThis() throws Exception {
        Integer year = Integer.parseInt("biezhi???");
        System.out.println("哦 " + year);
    }

    public void doThis() throws NumberFormatException {
        Integer year = Integer.parseInt("biezhi???");
        System.out.println("哦 " + year);
    }
}

3.3 Example3.java

/**
 * 给异常加点说明
 *
 * @author biezhi
 * @date 2018/9/18
 */
public class Example3 {

    class NotFoundGirlFriendException extends Exception {
        public NotFoundGirlFriendException(String message) {
            super(message);
        }
    }

    /**
     * 当心抛出 NotFoundGirlFriendException...
     *
     * @param input
     * @throws NotFoundGirlFriendException 如果你不订阅 ... 那么😁😁😁
     */
    public void doSomething(String input) throws NotFoundGirlFriendException {

    }
}

3.4 Example4.java

/**
 * 使用描述性消息抛出异常
 *
 * @author biezhi
 * @date 2018/9/18
 */
public class Example4 {

    private static final Logger log = LoggerFactory.getLogger(Example4.class);

    public void foo() {
        try {
            new Long("biezhi大法好");
        } catch (NumberFormatException e) {
            log.error("用户ID格式化失败", e);
        }
    }
}

3.5 Example5.java

/**
 * 优先捕获具体异常
 * @author biezhi
 * @date 2018/9/18
 */
public class Example5 {

    private static final Logger log = LoggerFactory.getLogger(Example5.class);

    public void catchMostSpecificExceptionFirst() {
        try {
            doSomething("不要跟我讲这些,因为我只是一只小猫咪!");
            //这里应该优先捕获 NumberFormatException
        } catch (NumberFormatException e) {
            log.error("字符串转数字失败", e);
        } catch (IllegalArgumentException e) {
            log.error("非法参数", e);
        }
    }

    private void doSomething(String message) {
        Integer emmm = Integer.parseInt(message);
    }

    public static void main(String[] args) {
        new Example5().catchMostSpecificExceptionFirst();
    }

}

3.6 Example6.java

/**
 * 不要捕获 Throwable,因为Throwable 包括 Exception 和 Error
 *
 * @author biezhi
 * @date 2018/9/18
 */
public class Example6 {

    public void doNotCatchThrowable() {
        try {
            // 做点什么吧
        } catch (Throwable t) {
            // 停下来,不要 🙅 这么干
        }
    }
}

3.7 Example7.java

/**
 * 不要忽略异常
 *
 * @author biezhi
 * @date 2018/9/18
 */
public class Example7 {

    private static final Logger log = LoggerFactory.getLogger(Example7.class);

    public void doNotIgnoreExceptions() {
        try {
            // 做点什么吧,先生
        } catch (NumberFormatException e) {
            // 嘤该不会走到这里(不,一定不会的)
            log.error("不可能走到的", e);
        }
    }
}

3.8 Example8.java

/**
 * 不要同时记录并抛出异常
 *
 * @author biezhi
 * @date 2018/9/18
 */
public class Example8 {

    private static final Logger log = LoggerFactory.getLogger(Example8.class);

    public void foo() {
        try {
            new Long("xyz");
        } catch (NumberFormatException e) {
        	//只记录一次异常
//            log.error("", e);
            throw e;
        }
    }

    public static void main(String[] args) {
        new Example8().foo();
    }
}

3.9 Example9.java

/**
 * 包装异常不要丢弃原始异常
 *
 * @author biezhi
 * @date 2018/9/18
 */
public class Example9 {

    class MyBusinessException extends Exception {
        public MyBusinessException(String message) {
            super(message);
        }
        public MyBusinessException(String message, Throwable cause) {
            super(message, cause);
        }

    }

    public void wrapException(String id) throws MyBusinessException {
        try {
            long userId = Long.parseLong(id);
            System.out.println("userId: " + userId);
        } catch (NumberFormatException e) {
        	//错误写法,抛弃了原始的异常 e 
        	// throw new MyBusinessException("描述错误的消息");
            throw new MyBusinessException("描述错误的消息", e);
        }
    }

    public static void main(String[] args) throws MyBusinessException {
        new Example9().wrapException("emmm");
    }

}
展开阅读全文
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值