不同风格的程序流程?

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

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

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

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

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

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

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

在这种情况下,在盲目执行写入之前实际测试路径存在会更好。

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

exception处理的一个很好的用法:(再次伪代码)

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

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

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

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

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

相反,你应该使用breakreturn或甚至(在一个真正的捏) goto

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

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

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

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

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

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

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

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

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

但是,出于多种原因,使用exception绝不是一个好主意:

  • 抛出exception相关的成本(即在Java中生成Throwable)
  • 控制流并不是很明显 – 例如,如果try块中的多个语句可以抛出NullPointerException,你怎么知道哪个在catch块中抛出它
  • 等等

他可能想要的是多种不执行一些代码的方法…而不是(在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) { } 

问题是如果抛出一些真正的exception怎么办? 我想如果他想要缩进缩进,你的同事应该写什么是这样的:

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

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

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

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