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

时间:2021-11-30 15:43:58

Today I had a coworker suggest I refactor my code to use a label statement to control flow through 2 nested for loops I had created. I've never used them before because personally I think they decrease the readability of a program. I am willing to change my mind about using them if the argument is solid enough however. What are people's opinions on label statements?

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

11 个解决方案

#1


49  

Many algorithms are expressed more easily if you can jump across two loops (or a loop containing a switch statement). Don't feel bad about it. On the other hand, it may indicate an overly complex solution. So stand back and look at the problem.

如果可以跨越两个循环(或包含switch语句的循环),则可以更容易地表达许多算法。不要为此感到难过。另一方面,它可能表明解决方案过于复杂。所以退后,看看这个问题。

Some people prefer a "single entry, single exit" approach to all loops. That is to say avoiding break (and continue) and early return for loops altogether. This may result in some duplicate code.

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

What I would strongly avoid doing is introducing auxilary variables. Hiding control-flow within state adds to confusion.

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

Splitting labeled loops into two methods may well be difficult. Exceptions are probably too heavyweight. Try a single entry, single exit approach.

将带标签的循环分解为两种方法可能很困难。例外可能太过沉重。尝试一个单一的入口,单一的出口方式。

#2


32  

Labels are like goto's: Use them sparingly, and only when they make your code faster and more importantly, more understandable,

标签就像goto的:谨慎地使用它们,只有当它们让你的代码更快,更重要的是,更容易理解,

e.g., If you are in big loops six levels deep and you encounter a condition that makes the rest of the loop pointless to complete, there's no sense in having 6 extra trap doors in your condition statements to exit out the loop early.

例:如果你在六层的大循环中,你遇到了一种情况,使得循环的其余部分毫无意义地完成,那么在你的条件语句中增加6个陷阱门来尽早退出循环就没有意义了。

Labels (and goto's) aren't evil, it's just that sometimes people use them in bad ways. Most of the time we are actually trying to write our code so it is understandable for you and the next programmer who comes along. Making it uber-fast is a secondary concern (be wary of premature optimization).

标签(和goto’s)并不是邪恶的,只是有时候人们用得不好。大多数时候,我们实际上是在尝试编写代码,这样您和下一个出现的程序员就可以理解了。使它超快是次要考虑的问题(要警惕过早的优化)。

When Labels (and goto's) are misused they make the code less readable, which causes grief for you and the next developer. The compiler doesn't care.

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

#3


27  

There are few occasions when you need labels and they can be confusing because they are rarely used. However if you need to use one then use one.

当你需要标签的时候,很少会有这样的情况,因为它们很少被使用。但是,如果您需要使用一个,那么请使用一个。

BTW: this compiles and runs.

这个编译和运行。

class MyFirstJavaProg {  
        public static void main(String args[]) {
           http://www.javacoffeebreak.com/java101/java101.html
           System.out.println("Hello World!");
        }
}

#4


8  

I'm curious to hear what your alternative to labels is. I think this is pretty much going to boil down to the argument of "return as early as possible" vs. "use a variable to hold the return value, and only return at the end."

我很想知道你对标签的选择是什么。我认为这基本上可以归结为“尽早返回”vs。“使用一个变量来保存返回值,并且只在末尾返回。”

Labels are pretty standard when you have nested loops. The only way they really decrease readability is when another developer has never seen them before and doesn't understand what they mean.

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

#5


5  

I've never seen labels used "in the wild" in Java code. If you really want to break across nested loops, see if you can refactor your method so that an early return statement does what you want.

我从未见过在Java代码中使用“in the wild”标签。如果你真的想要打破嵌套循环,看看你是否可以重构你的方法,这样早期的返回语句就可以实现你想要的。

Technically, I guess there's not much difference between an early return and a label. Practically, though, almost every Java developer has seen an early return and knows what it does. I'd guess many developers would at least be surprised by a label, and probably be confused.

从技术上讲,我想早期的回报和标签之间并没有太大的区别。但是实际上,几乎每个Java开发人员都已经看到了早期的回报,并且知道它是做什么的。我猜许多开发人员至少会对一个标签感到惊讶,并且可能会感到困惑。

I was taught the single entry / single exit orthodoxy in school, but I've since come to appreciate early return statements and breaking out of loops as a way to simplify code and make it clearer.

我在学校学过“单入口/单出口”的正统思想,但后来我开始欣赏早期的返回语句,并打破循环,以简化代码并使其更清晰。

#6


5  

I'd argue in favour of them in some locations, I found them particularly useful in this example:

在某些地方,我赞成使用它们,我发现它们在这个例子中特别有用:


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  

I think with the new for-each loop, the label can be really clear.

我认为使用新的for-each循环,标签可以非常清晰。

For example:

例如:

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

I think that looks really clear by having your label the same as your variable in the new for-each. In fact, maybe Java should be evil and add implicit labels for-each variables heh

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

#8


5  

I have use a Java labeled loop for an implementation of a Sieve method to find prime numbers (done for one of the project Euler math problems) which made it 10x faster compared to nested loops. Eg if(certain condition) go back to outer loop.

我使用了一个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

I asked a C++ programmer how bad labeled loops are, he said he would use them sparingly, but they can occasionally come in handy. For example, if you have 3 nested loops and for certain conditions you want to go back to the outermost loop.

我问一个c++程序员标记的循环有多糟糕,他说他会谨慎地使用它们,但它们偶尔会派上用场。例如,如果您有3个嵌套循环,并且对于某些条件,您希望返回到最外层循环。

So they have their uses, it depends on the problem you were trying to solve.

它们有各自的用途,这取决于你要解决的问题。

#9


3  

I never use labels in my code. I prefer to create a guard and initialize it to null or other unusual value. This guard is often a result object. I haven't seen any of my coworkers using labels, nor found any in our repository. It really depends on your style of coding. In my opinion using labels would decrease the readability as it's not a common construct and usually it's not used in Java.

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

#10


1  

Yes, you should avoid using label unless there's a specific reason to use them (the example of it simplifying implementation of an algorithm is pertinent). In such a case I would advise adding sufficient comments or other documentation to explain the reasoning behind it so that someone doesn't come along later and mangle it out of some notion of "improving the code" or "getting rid of code smell" or some other potentially BS excuse.

是的,您应该避免使用label,除非有特定的理由使用它们(它简化算法实现的示例是相关的)。在这种情况下,我建议添加足够的注释或其他文档来解释其背后的原因,这样以后就不会有人来把它从“改进代码”或“摆脱代码味道”或其他可能的b类借口中剔除。

I would equate this sort of question with deciding when one should or shouldn't use the ternary if. The chief rationale being that it can impede readability and unless the programmer is very careful to name things in a reasonable way then use of conventions such as labels might make things a lot worse. Suppose the example using 'nextCondition' and 'nextItem' had used 'loop1' and 'loop2' for his label names.

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

Personally labels are one of those features that don't make a lot of sense to me, outside of Assembly or BASIC and other similarly limited languages. Java has plenty of more conventional/regular loop and control constructs.

就个人而言,标签是一种对我来说不太有意义的功能,在装配或基础和其他类似的有限语言之外。Java有许多更常规的/常规的循环和控制结构。

#11


0  

I found labels to be sometimes useful in tests, to separate the usual setup, excercise and verify phases and group related statements. For example, using the BDD terminology:

我发现标签有时在测试中很有用,它可以分离通常的设置、执行和验证阶段以及分组相关的语句。例如,使用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();
}

Your formatting choices may vary but the core idea is that labels, in this case, provide a noticeable distinction between the logical sections comprising your test, better than comments can. I think the Spock library just builds on this very feature to declare its test phases.

您的格式选择可能会有所不同,但核心思想是,在本例中,标签在组成测试的逻辑部分之间提供了明显的区别,比注释更好。我认为Spock库只是基于这个特性来声明它的测试阶段。

#1


49  

Many algorithms are expressed more easily if you can jump across two loops (or a loop containing a switch statement). Don't feel bad about it. On the other hand, it may indicate an overly complex solution. So stand back and look at the problem.

如果可以跨越两个循环(或包含switch语句的循环),则可以更容易地表达许多算法。不要为此感到难过。另一方面,它可能表明解决方案过于复杂。所以退后,看看这个问题。

Some people prefer a "single entry, single exit" approach to all loops. That is to say avoiding break (and continue) and early return for loops altogether. This may result in some duplicate code.

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

What I would strongly avoid doing is introducing auxilary variables. Hiding control-flow within state adds to confusion.

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

Splitting labeled loops into two methods may well be difficult. Exceptions are probably too heavyweight. Try a single entry, single exit approach.

将带标签的循环分解为两种方法可能很困难。例外可能太过沉重。尝试一个单一的入口,单一的出口方式。

#2


32  

Labels are like goto's: Use them sparingly, and only when they make your code faster and more importantly, more understandable,

标签就像goto的:谨慎地使用它们,只有当它们让你的代码更快,更重要的是,更容易理解,

e.g., If you are in big loops six levels deep and you encounter a condition that makes the rest of the loop pointless to complete, there's no sense in having 6 extra trap doors in your condition statements to exit out the loop early.

例:如果你在六层的大循环中,你遇到了一种情况,使得循环的其余部分毫无意义地完成,那么在你的条件语句中增加6个陷阱门来尽早退出循环就没有意义了。

Labels (and goto's) aren't evil, it's just that sometimes people use them in bad ways. Most of the time we are actually trying to write our code so it is understandable for you and the next programmer who comes along. Making it uber-fast is a secondary concern (be wary of premature optimization).

标签(和goto’s)并不是邪恶的,只是有时候人们用得不好。大多数时候,我们实际上是在尝试编写代码,这样您和下一个出现的程序员就可以理解了。使它超快是次要考虑的问题(要警惕过早的优化)。

When Labels (and goto's) are misused they make the code less readable, which causes grief for you and the next developer. The compiler doesn't care.

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

#3


27  

There are few occasions when you need labels and they can be confusing because they are rarely used. However if you need to use one then use one.

当你需要标签的时候,很少会有这样的情况,因为它们很少被使用。但是,如果您需要使用一个,那么请使用一个。

BTW: this compiles and runs.

这个编译和运行。

class MyFirstJavaProg {  
        public static void main(String args[]) {
           http://www.javacoffeebreak.com/java101/java101.html
           System.out.println("Hello World!");
        }
}

#4


8  

I'm curious to hear what your alternative to labels is. I think this is pretty much going to boil down to the argument of "return as early as possible" vs. "use a variable to hold the return value, and only return at the end."

我很想知道你对标签的选择是什么。我认为这基本上可以归结为“尽早返回”vs。“使用一个变量来保存返回值,并且只在末尾返回。”

Labels are pretty standard when you have nested loops. The only way they really decrease readability is when another developer has never seen them before and doesn't understand what they mean.

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

#5


5  

I've never seen labels used "in the wild" in Java code. If you really want to break across nested loops, see if you can refactor your method so that an early return statement does what you want.

我从未见过在Java代码中使用“in the wild”标签。如果你真的想要打破嵌套循环,看看你是否可以重构你的方法,这样早期的返回语句就可以实现你想要的。

Technically, I guess there's not much difference between an early return and a label. Practically, though, almost every Java developer has seen an early return and knows what it does. I'd guess many developers would at least be surprised by a label, and probably be confused.

从技术上讲,我想早期的回报和标签之间并没有太大的区别。但是实际上,几乎每个Java开发人员都已经看到了早期的回报,并且知道它是做什么的。我猜许多开发人员至少会对一个标签感到惊讶,并且可能会感到困惑。

I was taught the single entry / single exit orthodoxy in school, but I've since come to appreciate early return statements and breaking out of loops as a way to simplify code and make it clearer.

我在学校学过“单入口/单出口”的正统思想,但后来我开始欣赏早期的返回语句,并打破循环,以简化代码并使其更清晰。

#6


5  

I'd argue in favour of them in some locations, I found them particularly useful in this example:

在某些地方,我赞成使用它们,我发现它们在这个例子中特别有用:


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  

I think with the new for-each loop, the label can be really clear.

我认为使用新的for-each循环,标签可以非常清晰。

For example:

例如:

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

I think that looks really clear by having your label the same as your variable in the new for-each. In fact, maybe Java should be evil and add implicit labels for-each variables heh

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

#8


5  

I have use a Java labeled loop for an implementation of a Sieve method to find prime numbers (done for one of the project Euler math problems) which made it 10x faster compared to nested loops. Eg if(certain condition) go back to outer loop.

我使用了一个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

I asked a C++ programmer how bad labeled loops are, he said he would use them sparingly, but they can occasionally come in handy. For example, if you have 3 nested loops and for certain conditions you want to go back to the outermost loop.

我问一个c++程序员标记的循环有多糟糕,他说他会谨慎地使用它们,但它们偶尔会派上用场。例如,如果您有3个嵌套循环,并且对于某些条件,您希望返回到最外层循环。

So they have their uses, it depends on the problem you were trying to solve.

它们有各自的用途,这取决于你要解决的问题。

#9


3  

I never use labels in my code. I prefer to create a guard and initialize it to null or other unusual value. This guard is often a result object. I haven't seen any of my coworkers using labels, nor found any in our repository. It really depends on your style of coding. In my opinion using labels would decrease the readability as it's not a common construct and usually it's not used in Java.

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

#10


1  

Yes, you should avoid using label unless there's a specific reason to use them (the example of it simplifying implementation of an algorithm is pertinent). In such a case I would advise adding sufficient comments or other documentation to explain the reasoning behind it so that someone doesn't come along later and mangle it out of some notion of "improving the code" or "getting rid of code smell" or some other potentially BS excuse.

是的,您应该避免使用label,除非有特定的理由使用它们(它简化算法实现的示例是相关的)。在这种情况下,我建议添加足够的注释或其他文档来解释其背后的原因,这样以后就不会有人来把它从“改进代码”或“摆脱代码味道”或其他可能的b类借口中剔除。

I would equate this sort of question with deciding when one should or shouldn't use the ternary if. The chief rationale being that it can impede readability and unless the programmer is very careful to name things in a reasonable way then use of conventions such as labels might make things a lot worse. Suppose the example using 'nextCondition' and 'nextItem' had used 'loop1' and 'loop2' for his label names.

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

Personally labels are one of those features that don't make a lot of sense to me, outside of Assembly or BASIC and other similarly limited languages. Java has plenty of more conventional/regular loop and control constructs.

就个人而言,标签是一种对我来说不太有意义的功能,在装配或基础和其他类似的有限语言之外。Java有许多更常规的/常规的循环和控制结构。

#11


0  

I found labels to be sometimes useful in tests, to separate the usual setup, excercise and verify phases and group related statements. For example, using the BDD terminology:

我发现标签有时在测试中很有用,它可以分离通常的设置、执行和验证阶段以及分组相关的语句。例如,使用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();
}

Your formatting choices may vary but the core idea is that labels, in this case, provide a noticeable distinction between the logical sections comprising your test, better than comments can. I think the Spock library just builds on this very feature to declare its test phases.

您的格式选择可能会有所不同,但核心思想是,在本例中,标签在组成测试的逻辑部分之间提供了明显的区别,比注释更好。我认为Spock库只是基于这个特性来声明它的测试阶段。