|
|
51CTO旗下网站
|
|
移动端

Java:异常作为控制流?大佬:避免!避免!避免

用异常(Exceptions)作为控制流就是这些常见的不良做法中的一种。要避免使用这一方法的原因有二:首先,这会降低单位时间内代码的响应性能,同时代码也会非常难读懂。

作者:读芯术来源:读芯术|2019-11-21 08:51

Java是一种通用的编程语言,它有着许多不同的方案去解决一些特殊的问题。然而,其中既有需要被遵循的最佳做法,也有一些仍被普遍使用的不良做法。

用异常(Exceptions)作为控制流就是这些常见的不良做法中的一种。要避免使用这一方法的原因有二:首先,这会降低单位时间内代码的响应性能,同时代码也会非常难读懂。

通过下面这个例子来看看异常是怎样被用作控制流的。这个代码的商业用例是:

  1. publicstaticintfindAge(String name) {  
  2. try {  
  3. String ageAsString = findUser(name);  
  4. return ageAsString.length();  
  5. } catch (NameNotFoundException e) {  
  6. return0;  
  7.  
  8.  
  9. privatestaticStringfindUser(String name) {  
  10. if(name==null) {  
  11. thrownew NameNotFoundException();  
  12.  
  13. return name;  

如果用户提供了一个非空的名字给findAge 方法,那它会返回这个名字的长度。但是如果用户名为空,那么findUser方法会抛出NameNotFoundException,而在这种情况下,findAge 方法会返回0。

那该如何重构这个代码来避免异常呢?

Java:异常作为控制流?大佬:避免!避免!避免

老实说,有很多种办法可以实现,这里就只介绍一种。

  1. publicstaticintfindAgeNoEx(String name) {  
  2. String ageAsString = findUserNoEx(name);  
  3. return ageAsString.length();  
  4.  
  5. privatestaticStringfindUserNoEx(String name) {  
  6. if(name==null) {  
  7. return"";  
  8.  
  9. return name;  

为了找到异常对代码性能的影响,准备下面这个代码,其中两种实现都被执行了1000万次,Intel Core i7-3630QM CPU上运行时,异常花费了上千毫秒。

  1. publicclassControlFlowWithExceptionOrNot {  
  2. publicstaticclassNameNotFoundExceptionextends RuntimeException {  
  3. privatestaticfinallong serialVersionUID = 3L 
  4.  
  5. privatestaticfinalint TRIAL = 10000000 
  6. publicstaticvoid main(String[] args) throws InterruptedException {  
  7. long start = System.currentTimeMillis();  
  8. for (int i = 0; i < TRIAL; i++) {  
  9. findAgeNoEx(null);  
  10.  
  11. System.out.println("Duration :" + (System.currentTimeMillis() - start));  
  12. long start2 = System.currentTimeMillis();  
  13. for (int i = 0; i < TRIAL; i++) {  
  14. findAge(null);  
  15.  
  16. System.out.println("Duration :" + (System.currentTimeMillis() - start2));  
  17. };  
  18. publicstaticint findAge(String name) {  
  19. try {  
  20. String ageAsString = findUser(name);  
  21. return ageAsString.length();  
  22. } catch (NameNotFoundException e) {  
  23. return0;  
  24.  
  25.  
  26. privatestaticString findUser(String name) {  
  27. if (name == null) {  
  28. thrownew NameNotFoundException();  
  29.  
  30. return name;  
  31.  
  32. publicstaticint findAgeNoEx(String name) {  
  33. String ageAsString = findUserNoEx(name);  
  34. return ageAsString.length();  
  35.  
  36. privatestaticString findUserNoEx(String name) {  
  37. if (name == null) {  
  38. return"";  
  39.  
  40. return name;  
  41.  
  42.  

输出:

  1. Duration :16  
  2. Duration :6212 

如果来比较一下这两种findAge方法的可读性,可以发现没有异常的那个十分清晰,不管findUser方法返回什么,findAge方法都会得到它的长度,我们也很确信findUser方法会返回一个字符串。但是那个有异常的就会令人困惑,findUser方法返回不清晰,它可能返回一个字符串也可能抛出一个异常,而且这在方法的签名上是不可见的。正因为这样,函数式编程范式中不欢迎异常。

最后,在碰到真正的异常情况时再使用异常会比较好。如果你将异常用作控制流,这可能会导致性能问题,代码的可读性也会减弱。

【编辑推荐】

  1. 灵魂拷问:Java 的 substring() 是如何工作的?
  2. Java升级那么快,多个版本如何灵活切换和管理?
  3. 新消息!Java、JavaScript连续多年成为很受欢迎的编程语言
  4. Java世界常用的工具类库
  5. Java程序员必备:异常的十个关键知识点
【责任编辑:赵宁宁 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

骨干网与数据中心建设案例

骨干网与数据中心建设案例

高级网工必会
共20章 | 捷哥CCIE

394人订阅学习

中间件安全防护攻略

中间件安全防护攻略

4类安全防护
共4章 | hack_man

141人订阅学习

CentOS 8 全新学习术

CentOS 8 全新学习术

CentOS 8 正式发布
共16章 | UbuntuServer

288人订阅学习

读 书 +更多

C#2005编程进阶与参考手册

本书非常详细而全面地介绍了C#程序设计语言。本书不是“5分钟学习C#”式的手册,也不是那种教您“照猫画虎”地创建一些与您的实际工作需要...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO官微