优雅地处理异常真是一门学问啊!(2)

简介: 优雅地处理异常真是一门学问啊!

04、建议


关于异常处理机制的使用,我这里总结了一些非常实用的建议,希望你能够采纳。


1)尽量捕获原始的异常。


实际应该捕获 FileNotFoundException,却捕获了泛化的 Exception。示例如下。


InputStream is = null;
try {
  is = new FileInputStream("沉默王二.txt");
} catch (Exception e) {
  e.printStackTrace();
}


这样做的坏处显而易见:假如你喊“王二”,那么我就敢答应;假如你喊“老王”,那么我还真不敢答应,万一你喊的我妹妹“王三”呢?


很多初学者误以为捕获泛化的 Exception 更省事,但也更容易让人“丈二和尚摸不着头脑”。相反,捕获原始的异常能够让协作者更轻松地辨识异常类型,更容易找出问题的根源。


2)尽量不要打印堆栈后再抛出异常


当异常发生时打印它,然后重新抛出它,以便调用者能够适当地处理它。就像下面这段代码一样。


public static void main(String[] args) throws IOException {
  try (InputStream is = new FileInputStream("沉默王二.txt")) {
  }catch (IOException e) {
  e.printStackTrace();
  throw e;
  } 
}


这似乎考虑得很周全,但是这样做的坏处是调用者可能也打印了异常,重复的打印信息会增添排查问题的难度。


java.io.FileNotFoundException: 沉默王二.txt (系统找不到指定的文件。)
  at java.io.FileInputStream.open0(Native Method)
  at java.io.FileInputStream.open(FileInputStream.java:195)
  at java.io.FileInputStream.<init>(FileInputStream.java:138)
  at java.io.FileInputStream.<init>(FileInputStream.java:93)
  at learning.Test.main(Test.java:10)
Exception in thread "main" java.io.FileNotFoundException: 沉默王二.txt (系统找不到指定的文件。)
  at java.io.FileInputStream.open0(Native Method)
  at java.io.FileInputStream.open(FileInputStream.java:195)
  at java.io.FileInputStream.<init>(FileInputStream.java:138)
  at java.io.FileInputStream.<init>(FileInputStream.java:93)
  at learning.Test.main(Test.java:10)



3)千万不要用异常处理机制代替判断


我曾见过类似下面这样奇葩的代码,本来应该判 null 的,结果使用了异常处理机制来代替。


public static void main(String[] args) {
  try {
  String str = null;
  String[] strs = str.split(",");
  } catch (NullPointerException e) {
  e.printStackTrace();
  }
}


捕获异常相对判断花费的时间要多得多!我们可以模拟两个代码片段来对比一下。


代码片段 A:


long a = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
  try {
  String str = null;
  String[] strs = str.split(",");
  } catch (NullPointerException e) {
  }
}
long b = System.currentTimeMillis();
System.out.println(b - a);


代码片段 B:


long a = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
  String str = null;
  if (str != null) {
  String[] strs = str.split(",");
  }
}
long b = System.currentTimeMillis();
System.out.println(b - a);

100000 万次的循环,代码片段 A(异常处理机制)执行的时间大概需要 1983 毫秒;代码片段 B(正常判断)执行的时间大概只需要 1 毫秒。这样的比较虽然不够精确,但足以说明问题。


4)不要盲目地过早捕获异常


如果盲目地过早捕获异常的话,通常会导致更严重的错误和其他异常。请看下面的例子。

InputStream is = null;
try {
  is = new FileInputStream("沉默王二.txt");
} catch (FileNotFoundException e) {
  e.printStackTrace();
}
int b;
try {
  while ((b = is.read()) != -1) {
  }
} catch (IOException e) {
  e.printStackTrace();
}
finally {
  try {
  is.close();
  } catch (IOException e) {
  e.printStackTrace();
  }
}



假如文件没有找到的话,InputStream 的对象引用 is 就为 null,新的 NullPointerException 就会出现。


java.io.FileNotFoundException: 沉默王二.txt (系统找不到指定的文件。)
  at java.io.FileInputStream.open0(Native Method)
  at java.io.FileInputStream.open(FileInputStream.java:195)
  at java.io.FileInputStream.<init>(FileInputStream.java:138)
  at java.io.FileInputStream.<init>(FileInputStream.java:93)
  at learning.Test.main(Test.java:12)
Exception in thread "main" java.lang.NullPointerException
  at learning.Test.main(Test.java:28)


NullPointerException 并不是程序出现问题的本因,但实际上它出现了,无形当中干扰了我们的视线。正确的做法是延迟捕获异常,让程序在第一个异常捕获后就终止执行。


05、最后


好了,关于异常我们就说到这。异常处理是程序开发中必不可少的操作之一,但如何正确优雅地对异常进行处理却是一门学问,好的异常处理机制可以确保程序的健壮性,提高系统的可用率。

相关文章
|
5月前
如何更好的学习一门计算机语言
如何更好的学习一门计算机语言
30 1
|
7月前
|
JavaScript 前端开发 Java
编程语言常识
编程语言常识
|
8月前
|
前端开发 JavaScript Java
编程其实是一门武林绝学,你是哪个门派?
编程其实是一门武林绝学,你是哪个门派?
89 0
|
JavaScript 前端开发 Java
59条有趣的程序员编程箴言
  下面收集的语录涉及软件开发、代码维护、调试纠错、软件bug、系统设计、文档、代码质量、测试和软件开发团队管理等方面。虽然它们有些搞笑,但却真实无比。只有程序员才能理解这些编程语句里的真正内涵。
184 0
|
程序员
请问各位程序员,是我的思维方式有错误吗? (中)
请问各位程序员,是我的思维方式有错误吗? (中)
101 0
请问各位程序员,是我的思维方式有错误吗? (中)
|
前端开发 Dubbo Java
请问各位程序员,是我的思维方式有错误吗? (下)
请问各位程序员,是我的思维方式有错误吗? (下)
128 0
请问各位程序员,是我的思维方式有错误吗? (下)
|
自然语言处理 程序员
程序员英语高效学习法
大多数程序员的英语是软肋,包括我在内。自己也曾经试过多种方法来学习英语,但最后都是不了了之,现在回想起来,
程序员英语高效学习法
|
程序员 定位技术
我21年编程生涯中的21个错误
  从我21年的编程中学到的经验教训。   2022年1月18日。今天对我来说是美好的一天。 我终于完成了21年编程。   ew! 好像昨天和今天在这里一样,我的内心写着一个40岁的中年程序员,他成功地度过了软件行业这个危险世界的正弦波峰和波谷。 是的,至少对我来说,这是决定性的时刻。   话虽如此,犯错是实现卓越的学习途径的一部分。 快速且经常失败是成功的标志。 为了避免多次犯同样的错误,应该放在优先列表上。   是的,个人经验是最有效的学习方法,但是通过他人的经验获得的知识是一种更快,更聪明的方法,可以减轻痛苦。 毕竟,生命是短暂的。 您不可能一生中犯下所有可能的错误。   软件
106 0