代码之家  ›  专栏  ›  技术社区  ›  Aaron

我应该避免使用Java标签语句吗?

  •  67
  • Aaron  · 技术社区  · 18 年前

    今天我有个同事建议我重构代码,使用label语句来控制通过我创建的2个嵌套for循环的流。我以前从未使用过它们,因为我个人认为它们会降低程序的可读性。不过,如果论点足够可靠,我愿意改变使用它们的想法。人们对标签声明有什么看法?

    11 回复  |  直到 9 年前
        1
  •  49
  •   Tom Hawtin - tackline    18 年前

    如果您可以跨越两个循环(或包含switch语句的循环),那么许多算法就更容易表示出来。别为此难过。另一方面,它可能表示一个过于复杂的解决方案。所以往后站,看看问题所在。

    有些人喜欢对所有循环使用“单入口、单出口”方法。也就是说,避免中断(并继续)和循环的早期返回。这可能会导致一些重复的代码。

    我极力避免的是引入辅助变量。在状态中隐藏控制流会增加混乱。

    将标记的循环拆分为两种方法可能很困难。例外可能太重了。尝试单一入口、单一出口方法。

        2
  •  33
  •   BIBD    10 年前

    标签就像goto的:谨慎地使用它们,并且只有当它们使您的代码更快时才使用它们。 和 更重要的是,更容易理解,

    例如,如果您在六个层次的大循环中,并且遇到了一个使循环的其余部分无法完成的条件,那么在条件语句中额外设置6个陷阱门来提前退出循环是没有意义的。

    标签(和goto的标签)并不是邪恶的,只是人们有时会以不好的方式使用它们。大多数时候,我们实际上是在试图编写代码,所以对于您和接下来的程序员来说,这是可以理解的。让它更快是第二个问题(注意提前优化)。

    当标签(和goto的)被误用时,它们会降低代码的可读性,这会给您和下一个开发人员带来痛苦。编译器不在乎。

        3
  •  27
  •   Community Mohan Dere    15 年前

    很少有场合需要标签,因为很少使用它们,所以会让人困惑。但是,如果你需要使用一个,那么就使用一个。

    顺便说一句:这编译并运行。

    class MyFirstJavaProg {  
            public static void main(String args[]) {
               http://www.javacoffeebreak.com/java101/java101.html
               System.out.println("Hello World!");
            }
    }
    
        4
  •  8
  •   Tim Frey    18 年前

    我很想知道你们的标签替代品是什么。我认为这基本上可以归结为“尽早返回”和“使用变量保存返回值,并且只在末尾返回”的参数。

    当您有嵌套循环时,标签是相当标准的。它们真正降低可读性的唯一方法是,其他开发人员以前从未见过它们,也不理解它们的含义。

        5
  •  5
  •   Don Kirkby    18 年前

    我从未见过在Java代码中使用“野生”标签。如果您真的想跨越嵌套循环,请查看您是否可以重构方法,以便早期的返回语句能够满足您的需要。

    从技术上讲,我想早退和标签没什么区别。实际上,几乎每一个Java开发人员都看到了早期的返回并知道它做了什么。我想很多开发人员至少会对一个标签感到惊讶,可能会感到困惑。

    我在学校里接受过单入口/单出口正统的教育,但后来我开始喜欢使用早期的返回语句和打破循环的方法来简化代码并使其更清晰。

        6
  •  5
  •   Ceilingfish    17 年前

    我会在一些地方支持它们,我发现它们在这个例子中特别有用:

    
    nextItem: for(CartItem item : user.getCart()) {
    
      nextCondition : for(PurchaseCondition cond : item.getConditions()) {
         if(!cond.check())
            continue nextItem;
         else
            continue nextCondition;
    
      }
      purchasedItems.add(item);
    }
    
        7
  •  5
  •   Pyrolistical    12 年前

    我想每个循环都有新的标签,标签会非常清晰。

    例如:

    sentence: for(Sentence sentence: paragraph) {
      for(String word: sentence) {
        // do something
        if(isDone()) {
          continue sentence;
        }
      }
    }
    

    我认为你的标签和每个变量的新标签一样,这看起来很清楚。事实上,也许Java应该是邪恶的,并且为每个变量添加隐式标签。

        8
  •  5
  •   Daniel Alder    9 年前

    我使用一个Java标记的循环来实现一个筛子方法来找到素数(完成一个项目Euler数学问题),这使得它比嵌套循环快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个嵌套循环,并且在某些情况下,您希望返回到最外层的循环。

    所以它们有它们的用途,这取决于你试图解决的问题。

        9
  •  3
  •   Bartosz Bierkowski    18 年前

    我从不在代码中使用标签。我更喜欢创建一个保护并将其初始化为 无效的 或其他不寻常的价值。这个保护通常是一个结果对象。我没有看到我的任何同事使用标签,也没有在我们的存储库中找到任何标签。这真的取决于您的编码风格。在我看来,使用标签会降低可读性,因为它不是一个常见的构造,通常不在Java中使用。

        10
  •  1
  •   Jeremy Harton    10 年前

    是的,您应该避免使用标签,除非有特定的理由使用它们(简化算法实现的示例是相关的)。在这种情况下,我建议添加足够的注释或其他文档来解释其背后的原因,这样就不会有人在以后出现,并将其从“改进代码”或“消除代码气味”或其他一些可能的BS借口的概念中删除。

    我将把这类问题等同于决定何时应该或不应该使用三元if。主要的理由是它会阻碍可读性,除非程序员非常小心地以合理的方式命名事物,否则使用诸如标签之类的约定可能会使事情变得更糟。假设使用“nextCondition”和“nextItem”的示例在其标签名称中使用了“loop1”和“loop2”。

    个人标签是那些对我没有太大意义的功能之一,除了汇编语言或基本语言和其他类似的有限语言。Java具有更多的常规/规则循环和控制结构。

        11
  •  0
  •   polaretto    10 年前

    我发现标签有时在测试中很有用,用于分离通常的设置、练习和验证阶段以及与组相关的语句。例如,使用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 库只是基于这个特性来声明它的测试阶段。