不同风格的程序流程?

时间:2010-08-18 18:54:38

标签: java c++

我是一名计算机科学专业的学生,​​所以我不知道那么多。

我最近和一位刚接受(java)软件开发人员工作的朋友谈话。他告诉我,在他的工作中有一个人在C ++方面很有经验,但不幸的是每次他用java编写代码时,他都会使用try-catch来控制程序的流程。据我的朋友说,这是一种错误的Java风格。这是真的?在C ++和Java之间使用try-catch(最终在java中)有什么不同(如果有的话)?

8 个答案:

答案 0 :(得分:28)

使用try-catch来控制程序的流程在任何地方都是错误的...异常处理就是它所说的:处理异常的情况。

当然,对于每个规则,都有十几个必要偏差的反例,但一般而言:不要控制程序流程,但有例外。

当您预计在正常操作环境中抛出某些异常时,会使用异常来控制程序流,并根据这些异常做出逻辑决策。

例如,以伪代码控制程序流程:

try {
  write update to file
} catch (IOException) {
  write update to alternate file
}

在这种情况下,最好在盲目执行写操作之前实际测试路径存在。

我删除了权限检查说明,因为这是一个不好的例子

异常处理的良好用法:(再次伪代码)

try {
  do stuff
} catch(OutOfMemoryException) {
  fail gracefully (don't try and do something else to achieve the same result)
}

答案 1 :(得分:8)

我想说从程序架构的角度来看,Java和C ++中异常的目的是相同的。它们应该用于处理特殊情况,而不是直接正常的程序流程。

反对使用例外的最常见论点是它们很慢。像大多数基于代码速度的参数一样,现在几乎总是无关紧要,尤其是在正确使用异常时。

答案 2 :(得分:6)

我认为他所说的是他正在使用例外的非常规条件,如正常的循环终止。在大多数提供异常的语言中,程序员都认为这是禁忌,包括C ++。

这样做的原因是异常往往会拖累相当多的信息。在某些平台上,它们将整个callstack带到异常点,以便在一个很好的调试消息中显示它。如果你真正想要的是一个无条件的控制跳跃,这是非常昂贵的。

相反,您应该使用breakreturn或甚至(真正的捏合)goto等语句。

答案 3 :(得分:4)

我希望C ++和Java世界在他们的观点中大致相似:

  1. 使用try / catch块进行流量控制并不是很明显
  2. 性能昂贵。在实践中,这可能不是问题,但在许多情况下(例如紧密循环),它肯定会对您产生影响。

答案 4 :(得分:3)

try / catch唯一目的是流量控制。它旨在让我们摆脱任何循环,甚至超越调用者并达到更高级别的功能。

但是,它是为异常条件而设计的,例如使用空引用,除法溢出或文件I / O失败。这些错误会阻止程序继续运行并且必须处理。一般来说,它们很难预测或非常罕见。

当出现异常情况时,最好的做法是改变控制流程,以便尽可能多地抛出异常,以便找到愿意处理它的catch块。中间的任何方法都会被中止和解除,即使它没有代码来检查结果。

当人们抱怨使用try / catch进行流量控制时,他们应该意味着它不是非特殊情况下的流量控制。如果你要做的就是退出循环,请使用breakreturn;不要抛出异常然后抓住它。这不是什么例外,也不是它们的好处。

答案 5 :(得分:2)

try-catch块用于在所有语言中执行相同的操作 - 例外是在出现问题时恢复的众多方法之一。在java中,以下两个语句是相同的:

if(x != null){
  //do the normal thing
}
else{
  //recover from the error
}

try{
  //do the normal thing
}
catch(NullPointerException ex){
  //recover
}

但是,出于多种原因,使用例外从来都不是好主意:

  • 与抛出异常相关的成本(即在Java中生成Throwable)
  • 控制流程并不是很明显 - 例如,如果try块中的多个语句可以抛出NullPointerException,那么如何判断哪一个在catch块中抛出它
  • 等等

答案 6 :(得分:1)

他可能想要的是多种不执行一些代码的方法...而不是(在java中)

if (cond1) {
  some_code();
  if (cond2) {
    some_more_code();
    if (condN) {
      ad_infinitum
    }
  }
}

这可以通过扔垃圾来“扁平化”......

try {
  if (!cond1) throw new Throwable();
  some_code();
  if (!cond2) throw new Throwable();
  some_more_code();
  if (!condN) throw new Throwable();
  ad_infinitum();
} catch (Throwable ignore) { }

问题是如果引发了一些真正的异常?我认为如果他想要缩进缩进,你的同事应该写的是这样的:

do {
  if (!cond1) break;
  some_code();
  if (!cond2) break;
  some_more_code();
  if (!condN) break;
  ad_infinitum();
} while (false);

因为do / while总是执行,所以我们可以使用break来逼近goto(只要它们都到达同一个地方)。

答案 7 :(得分:-2)

如果没有示例代码,您的问题就太模糊了。 C ++中没有finally

编辑通常,您不希望使用exceptions作为控制流量的方法。 Exceptions应该仅用于特殊(意外情况)情况。