在Java中使用标签打破了一个良好的习惯吗?

我盯着2001年的一些旧的代码,并且遇到了这样的说法:

else { do { int c = XMLDocumentFragmentScannerImpl.this.scanContent(); if (c == 60) { XMLDocumentFragmentScannerImpl.this.fEntityScanner.scanChar(); XMLDocumentFragmentScannerImpl.this.setScannerState(1); break label913: } 

我从来没有select过这个,在这里发现了一些标签:

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html

这不是基本function像goto ? 使用它甚至是好习惯吗? 这让我感到不安。

不,它不像转向,因为你不能“去”控制stream的另一部分。

从您链接的页面:

break语句终止标签语句; 它不会将控制stream转移到标签上。 控制stream被转移到紧随标签(已终止)语句之后的语句。

这意味着你只能打破当前正在执行的循环。

考虑这个例子:

 first: for( int i = 0; i < 10; i++) { second: for(int j = 0; j < 5; j ++ ) { break xxx; } } third: for( int a = 0; a < 10; a++) { } 

你可以用firstsecond替代xxx (打破外部或内部循环),因为两个循环都在执行,当你敲击break语句,但用thirdreplacexxx不会编译。

它并不像goto那么糟糕,因为它只是将控制权发送到标记语句的末尾(通常是一个循环结构)。 让goto变得不可思议的是,它是一个任意的分支,包括在方法源中find更高的标签,这样你就可以拥有本土的循环行为。 Java中的标签中断function不允许这种疯狂,因为控制只能向前发展。

我在12年前只使用过一次,在这种情况下,我需要摆脱嵌套循环,更多结构的替代scheme会在循环中进行更复杂的testing。 我不会build议使用它很多,但我不会将其标记为自动恶臭味。

在阅读本答案的其余部分之前,请阅读转至被视为有害的陈述 。 如果你不想全部阅读,这里是我认为的关键点:

肆无忌惮地使用go语句会立即产生一个结果,即要find一组描述过程进度的有意义的坐标变得非常困难。

或者换句话说, goto的问题在于程序可以在代码块的中间到达,程序员不需要了解程序状态。 标准的面向块的构造被devise为清楚地描述状态转换,标记的break旨在使程序进入特定的已知状态(在包含标记的块之外)。

在一个现实世界的命令性程序中,状态并没有被块界限清楚地界定,所以标记的break是否是一个好主意是值得怀疑的。 如果块更改块外部可见的状态,并且有多个点退出块,则标记的break等同于原始goto 。 唯一的区别是,你不是在一个不确定状态块的中间着陆的机会,而是开始一个不确定状态的新块。

所以,一般来说,我会认为有标签的break是危险的。 在我看来这是一个标志,该块应该被转换成一个函数,有限的访问范围。

但是,这个示例代码显然是parsing器生成器的产物(OP评论说它是Xerces源代码)。 parsing器生成器(或者一般的代码生成器)通常会对它们生成的代码感到自由,因为它们对状态有完全的了解,而且人们不需要理解它。

总是有可能用新的方法replacebreak

考虑代码检查两个列表中的任何常见元素:

 List list1, list2; boolean foundCommonElement = false; label: for (Object el : list1) { if (list2.contains(el)) { foundCommonElement = true; break label; } } 

你可以像这样重写它:

 boolean haveCommonElement(List list1, List list2) { for (Object el : list1) { if (list2.contains(el)) { return true; } } return false; } 

当然,为了检查两个列表之间的通用元素,最好使用list1.retainAll(new HashSet<>(list2))方法在O(n)O(n)额外的内存执行该操作,或者在O(n * log n) ,然后在O(n)find公共元素。

这不像goto语句,在你跳回stream量控制。 一个标签只是显示你(程序员)在哪里出现了中断。 另外,stream程控制在break之后转移到下一个语句。

关于使用它,我个人认为它没有什么大用处,因为一旦你开始编写价值数千行的代码,它就变得微不足道了。 但是,这又取决于用例。