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

发表于:2019-11-21 10:00

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:佚名    来源:读芯术

#
java
#
Java
  Java是一种通用的编程语言,它有着许多不同的方案去解决一些特殊的问题。然而,其中既有需要被遵循的最佳做法,也有一些仍被普遍使用的不良做法。
  用异常(Exceptions)作为控制流就是这些常见的不良做法中的一种。要避免使用这一方法的原因有二:首先,这会降低单位时间内代码的响应性能,同时代码也会非常难读懂。
  通过下面这个例子来看看异常是怎样被用作控制流的。这个代码的商业用例是:
   publicstaticintfindAge(String name) {
  try {
  String ageAsString = findUser(name);
  return ageAsString.length();
  } catch (NameNotFoundException e) {
  return0;
  }
  }
  privatestaticStringfindUser(String name) {
  if(name==null) {
  thrownew NameNotFoundException();
  }
  return name;
  }
  如果用户提供了一个非空的名字给findAge 方法,那它会返回这个名字的长度。但是如果用户名为空,那么findUser方法会抛出NameNotFoundException,而在这种情况下,findAge 方法会返回0。
  那该如何重构这个代码来避免异常呢?
  
  老实说,有很多种办法可以实现,这里就只介绍一种。
   publicstaticintfindAgeNoEx(String name) {
  String ageAsString = findUserNoEx(name);
  return ageAsString.length();
  }
  privatestaticStringfindUserNoEx(String name) {
  if(name==null) {
  return"";
  }
  return name;
  }
  为了找到异常对代码性能的影响,准备下面这个代码,其中两种实现都被执行了1000万次,Intel Core i7-3630QM CPU上运行时,异常花费了上千毫秒。
   publicclassControlFlowWithExceptionOrNot {
  publicstaticclassNameNotFoundExceptionextends RuntimeException {
  privatestaticfinallong serialVersionUID = 3L;
  }
  privatestaticfinalint TRIAL = 10000000;
  publicstaticvoid main(String[] args) throws InterruptedException {
  long start = System.currentTimeMillis();
  for (int i = 0; i < TRIAL; i++) {
  findAgeNoEx(null);
  }
  System.out.println("Duration :" + (System.currentTimeMillis() - start));
  long start2 = System.currentTimeMillis();
  for (int i = 0; i < TRIAL; i++) {
  findAge(null);
  }
  System.out.println("Duration :" + (System.currentTimeMillis() - start2));
  };
  publicstaticint findAge(String name) {
  try {
  String ageAsString = findUser(name);
  return ageAsString.length();
  } catch (NameNotFoundException e) {
  return0;
  }
  }
  privatestaticString findUser(String name) {
  if (name == null) {
  thrownew NameNotFoundException();
  }
  return name;
  }
  publicstaticint findAgeNoEx(String name) {
  String ageAsString = findUserNoEx(name);
  return ageAsString.length();
  }
  privatestaticString findUserNoEx(String name) {
  if (name == null) {
  return"";
  }
  return name;
  }
  }
  输出:
   Duration :16
  Duration :6212
  如果来比较一下这两种findAge方法的可读性,可以发现没有异常的那个十分清晰,不管findUser方法返回什么,findAge方法都会得到它的长度,我们也很确信findUser方法会返回一个字符串。但是那个有异常的就会令人困惑,findUser方法返回不清晰,它可能返回一个字符串也可能抛出一个异常,而且这在方法的签名上是不可见的。正因为这样,函数式编程范式中不欢迎异常。
  最后,在碰到真正的异常情况时再使用异常会比较好。如果你将异常用作控制流,这可能会导致性能问题,代码的可读性也会减弱。

      本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号