Java优化(二) 异常处理

白色玫瑰 程序猿

时间: 2023-05-22 阅读: 1 字数:9778

{}
Java中的异常(Exception)又称为例外,是一个在程序执行期间发生的事件,它中断正在执行程序的正常指令流。为了能够及时有效地处理程序中的运行错误,必须使用异常类。

目录

<a href="#1printStackTrace_8">1、不要使用printStackTrace()</a> <a href="#2Exception_31">2、不要用一个Exception捕捉所有异常</a> <a href="#3catch_64">3、不要在catch块中吃掉异常</a> <a href="#4finallytrywithresource_86">4、使用finally或者try-with-resource,关闭流资源</a> <a href="#5_141">5、捕获异常与抛出异常必须是完全匹配,或者捕获异常是抛异常的父类</a> <a href="#6_169">6、捕获到的异常,不能忽略</a> <a href="#7_194">7、注意异常对你的代码层次结构的侵染(早发现早处理)</a> <a href="#8Throwable_cause_216">8、自定义封装异常,不要丢弃原始异常的信息Throwable cause</a> <a href="#9_RuntimeExceptioncatch__296">9、 先预检查运行时异常RuntimeException,不应该通过catch 的方式来处理</a> <a href="#10_313">10、优先捕获具体的异常</a>

<hr> 在这里插入图片描述

1、不要使用printStackTrace()

反例:

      try {
         int i =1/0;
      } catch (Exception e) {
         e.printStackTrace();
      }

正例:

      try {
         int i =1/0;
      } catch (Exception e) {
         logger.error("异常信息:{}",e);
      }

注意!!!

printStackTrace()打印出的堆栈日志跟业务代码日志是交错混合在一起的,通常排查异常日志不太方便。 e.printStackTrace()语句产生的字符串记录的是堆栈信息,如果信息太长太多,字符串常量池所在的内存块没有空间了,即内存满了,那么,用户的请求就被卡住。

2、不要用一个Exception捕捉所有异常

反例:

public void test(){
   try{
      //…抛出 IOException 的代码调用
      //…抛出 SQLException 的代码调用
   }catch(Exception e){
      //用基类 Exception 捕捉的所有可能的异常,如果多个层次都这样捕捉,会丢失原始异常的有效信息哦
      logger.error(“Exception in test,exception:{}”, e);
   }
}

正例:

public void test(){
   try{
      //…抛出 IOException 的代码调用
      //…抛出 SQLException 的代码调用
   }catch(IOException e){
      //仅仅捕捉 IOException
      logger.error(“IOException in test,exception:{}”, e);
   }catch(SQLException e){
      //仅仅捕捉 SQLException
      logger.error(“SQLException in test,exception:{}”, e);
   }
}

注意!!!

用基类 Exception 捕捉的所有可能的异常,如果多个层次都这样捕捉,会丢失原始异常的有效信息

3、不要在catch块中吃掉异常

反例:

      try {
         int i =1/0;
      } catch (Exception e) {
         logger.error("异常信息");
      }

正例:

      try {
         int i =1/0;
      } catch (Exception e) {
         logger.error("异常信息:{}",e);
      }

注意!!!

没有把exception打印出来,这样异常就会被吞掉,无法获取到任何失败信息,会给日后的问题排查带来巨大困难。

4、使用finally或者try-with-resource,关闭流资源

反例:

      FileInputStream fileInputStream = null;
      try {
         fileInputStream = new FileInputStream(new File("/document.txt"));
         fileInputStream.close();
      } catch (FileNotFoundException e) {
         logger.error(e);
      } catch (IOException e) {
         logger.error(e);
      }

正例 1 使用finally关闭流资源:

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

正例 2 使用try-with-resource来处理:

      try (FileInputStream fis = new FileInputStream("D:\\小滴课堂\\a.txt");
          BufferedInputStream bis = new BufferedInputStream(fis);
          FileOutputStream fos = new FileOutputStream("D:\\小滴课堂\\b.txt");
          BufferedOutputStream bos = new BufferedOutputStream(fos);
      ) {
         int size;
         byte[] buf = new byte[1024];
         while ((size = bis.read(buf)) != -1) {
            bos.write(buf, 0, size);
         }
      } catch (Exception e) {
         logger.error(e);
      }
// 在try()里面定义多个资源,执行完成后会自动关闭,关闭顺序是最先关闭最后在try()中定义的资源。

注意!!!

如果不使用finally或者try-with-resource,当程序发生异常,IO资源流没关闭,那么这个IO资源就会被他一直占着,这样别人就没有办法用了,这就造成资源浪费。

5、捕获异常与抛出异常必须是完全匹配,或者捕获异常是抛异常的父类

反例:

//BizException 是 Exception 的子类
public class BizException extends Exception {}
//抛出父类Exception
public static void test() throws Exception {}

try {
    //编译错误
   test(); 
   //捕获异常子类是没法匹配
} catch (BizException e) { 
   log.error(e);
}

正例:

//抛出子类Exception
public static void test() throws BizException {}

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

6、捕获到的异常,不能忽略

反例:

public static void testIgnoreException() throws Exception {
   try {      
      int i =1/0;
   } catch (Exception e) {
      
   }
}

正例 :

public static void testIgnoreException() throws Exception {
   try {      
      int i =1/0;
   } catch (Exception e) {
      logger.error("异常信息:{}",e);
   }
}

注意!!!

虽然一个正常情况都不会发生的异常,但是如果你捕获到它,就不要忽略。

7、注意异常对你的代码层次结构的侵染(早发现早处理)

反例:

public UserInfo queryUserInfoByUserId(Long userid) throw SQLException {
   //根据用户Id查询数据库
}

正例 :

public UserInfo queryUserInfoByUserId(Long userid) {
   try{
      //根据用户Id查询数据库
   }catch(SQLException e){
      log.error("查询数据库异常啦,{}",e);
   }finally{
      //关闭连接,清理资源
   }
}

8、自定义封装异常,不要丢弃原始异常的信息Throwable cause

反例:

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 保存异常信息
         throw new MyException("文件在哪里呢");
      }
   }
   public void invokeReadFile() throws MyException{
      try {
         readFile();
      } catch (MyException e) {
         //e 保存异常信息
         throw new MyException("文件找不到");
      }
   }
   public static void main(String[] args) {
      TestChainException t = new TestChainException();
      try {
         t.invokeReadFile();
      } catch (MyException e) {
         e.printStackTrace();
      }
   }
}
//MyException 构造器
public MyException(String message) {
      super(message);
   }


正例 :


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 保存异常信息
         throw new MyException("文件在哪里呢", e);
      }
   }
   public void invokeReadFile() throws MyException{
      try {
         readFile();
      } catch (MyException e) {
         //e 保存异常信息
         throw new MyException("文件找不到", e);
      }
   }
   public static void main(String[] args) {
      TestChainException t = new TestChainException();
      try {
         t.invokeReadFile();
      } catch (MyException e) {
         e.printStackTrace();
      }
   }
}
//MyException 构造器
public MyException(String message, Throwable cause) {
      super(message, cause);
   }

9、 先预检查运行时异常RuntimeException,不应该通过catch 的方式来处理

反例:

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

正例 :

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

10、优先捕获具体的异常

注意异常的匹配顺序,因为只有第一个匹配到异常的catch块才会被执行。如果你希望看到,是NumberFormatException异常,就抛出NumberFormatException,如果是IllegalArgumentException就抛出IllegalArgumentException。 反例:

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

正例 :

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

注意!!!

因为NumberFormatException是IllegalArgumentException 的子类,反例中,不管是哪个异常,都会匹配到IllegalArgumentException,就不会再往下执行啦,因此不知道是否是NumberFormatException。所以需要优先捕获具体的异常,把NumberFormatException放前面。

原文地址:https://blog.csdn.net/dmjxsy/article/details/129664316?ops_request_misc=&request_id=&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2~all~koosearch~default-11-129664316-null-null.142^v87^koosearch_v1,239^v2^insert_chatgpt&utm_term=java%E4%BC%98%E5%8C%96

本文章网址:https://www.sjxi.cn/detil/294fa7e803de43c5b5e3087e1bb31372

最新评论

当前未登陆哦
登陆后才可评论哦

湘ICP备2021009447号

×

(穷逼博主)在线接单

QQ: 1164453243

邮箱: abcdsjx@126.com

前端项目代做
前后端分离
Python 爬虫脚本
Java 后台开发
各种脚本编写
服务器搭建
个人博客搭建
Web 应用开发
Chrome 插件编写
Bug 修复