今天,我有一个同事建议我重构代码,以使用label语句控制通过我创建的2个嵌套的for循环的流。我以前从未使用过它们,因为我个人认为它们会降低程序的可读性。如果论点足够扎实,我愿意改变使用它们的想法。人们对标签陈述有何看法?
Answers:
如果您可以跳过两个循环(或一个包含switch语句的循环),则许多算法的表达会更容易。不要为此感到难过。另一方面,它可能表明解决方案过于复杂。因此,退后一步,看看问题所在。
有些人喜欢在所有循环中使用“单入口单出口”方法。也就是说,完全避免了循环的中断(并继续)和提早返回。这可能会导致某些重复的代码。
我强烈避免做的是引入辅助变量。将控制流隐藏在状态内会增加混乱。
将标记的循环分为两种方法可能很困难。异常可能太重了。尝试一次进入,一次退出方法。
标签就像goto的标签:谨慎使用标签,只有在它们使您的代码更快,更重要,更易于理解时,
例如,如果您处于六个大级别的大循环中,并且遇到使循环的其余部分毫无意义地完成的条件,那么在条件语句中有6个额外的陷阱门就无法尽早退出循环是没有意义的。
标签(和goto的标签)不是邪恶的,只是有时人们以不良的方式使用它们。大多数时候,我们实际上是在尝试编写我们的代码,因此您和随之而来的下一个程序员都可以理解。使其超快是次要问题(请提防过早的优化)。
如果滥用标签(和goto的标签),它们会使代码的可读性降低,从而给您和下一个开发人员带来麻烦。编译器不在乎。
在极少数情况下,您需要标签,并且由于很少使用它们,因此可能会造成混淆。但是,如果您需要使用一个,请使用一个。
顺便说一句:这编译并运行。
class MyFirstJavaProg {
public static void main(String args[]) {
http://www.javacoffeebreak.com/java101/java101.html
System.out.println("Hello World!");
}
}
我使用Java标记的循环来实现Sieve方法的方法来查找质数(针对欧拉项目中的一个数学问题完成),这使其比嵌套循环快10倍。例如,如果(某些条件)返回外循环。
private static void testByFactoring() {
primes: for (int ctr = 0; ctr < m_toFactor.length; ctr++) {
int toTest = m_toFactor[ctr];
for (int ctr2 = 0; ctr2 < m_divisors.length; ctr2++) {
// max (int) Math.sqrt(m_numberToTest) + 1 iterations
if (toTest != m_divisors[ctr2]
&& toTest % m_divisors[ctr2] == 0) {
continue primes;
}
} // end of the divisor loop
} // end of primes loop
} // method
我问一个C ++程序员,标记循环有多坏,他说他会尽量少用它们,但是有时它们会派上用场。例如,如果您有3个嵌套循环,并且对于某些条件,则要返回最外层循环。
因此它们有其用途,这取决于您要解决的问题。
我认为使用新的for-each循环,标签可以非常清晰。
例如:
sentence: for(Sentence sentence: paragraph) {
for(String word: sentence) {
// do something
if(isDone()) {
continue sentence;
}
}
}
我认为通过在新的for-each中使标签与变量相同,可以很清楚地看出这一点。实际上,也许Java应该是邪恶的,并为每个变量添加隐式标签,呵呵
continue sentence;
就不会继续处理句子(哪个?)是由内部循环处理的话:它继续与_next sentence_ /同款。
我从不在代码中使用标签。我更喜欢创建一个防护并将其初始化为null或其他异常值。该防护通常是结果对象。我还没有看到任何同事使用标签,也没有在我们的存储库中找到任何同事。这实际上取决于您的编码风格。在我看来,使用标签会降低可读性,因为它不是常见的构造,并且通常不在Java中使用。
是的,除非有特殊原因使用标签,否则应避免使用标签(简化算法实现的示例与此相关)。在这种情况下,我建议添加足够的注释或其他文档来解释其背后的原因,以便以后不再有人提出来并使其脱离“改善代码”或“摆脱代码气味”的观念,或者其他潜在的BS借口。
我将这种问题等同于确定何时应该或不应该使用三元组if。最主要的理由是它可能会妨碍可读性,除非程序员非常谨慎地以合理的方式命名事物,否则使用诸如标签之类的约定可能会使事情变得更糟。假设使用“ nextCondition”和“ nextItem”的示例将“ loop1”和“ loop2”用作其标签名称。
个人标签是在Assembly或BASIC以及其他类似的受限语言之外对我而言没有太多意义的功能之一。Java具有许多更常规/常规的循环和控制构造。
我发现标签有时在测试中很有用,可以将通常的设置,锻炼和验证阶段以及与组相关的语句分开。例如,使用BDD术语:
@Test
public void should_Clear_Cached_Element() throws Exception {
given: {
elementStream = defaultStream();
elementStream.readElement();
Assume.assumeNotNull(elementStream.lastRead());
}
when:
elementStream.clearLast();
then:
assertThat(elementStream.lastRead()).isEmpty();
}
您的格式选择可能会有所不同,但核心思想是在这种情况下,标签在构成测试的逻辑部分之间提供了明显的区别,胜过注释。我认为Spock库只是基于此功能来声明其测试阶段。