[英]Should I avoid using Java Label Statements?
今天我有一個同事建議我重構我的代碼,使用label語句來控制我創建的2個嵌套for循環的流量。 我以前從未使用它們,因為我個人認為它們會降低程序的可讀性。 如果論證足夠堅實,我願意改變主意使用它們。 人們對標簽聲明的看法是什么?
如果您可以跳過兩個循環(或包含switch語句的循環),則可以更輕松地表達許多算法。 不要為此感到難過。 另一方面,它可能表明過於復雜的解決方案。 所以退后一步看看問題。
有些人更喜歡所有循環的“單入口,單出口”方法。 也就是說完全避免中斷(並繼續)和早期返回循環。 這可能會導致一些重復的代碼。
我強烈要避免做的是引入輔助變量。 隱藏在州內的控制流動增加了混亂。
將標記的循環分成兩種方法可能很困難。 例外情況可能太重了。 嘗試單入口,單退出方法。
標簽就像goto一樣:謹慎使用它們,只有當它們使代碼更快,更重要的是,更容易理解,
例如,如果你處於六級深度的大循環中並且遇到一個條件使得循環的其余部分無意義地完成,那么在條件語句中有6個額外的陷阱門以提前退出循環是沒有意義的。
標簽(和goto的)不是邪惡的,只是有時候人們以不好的方式使用它們。 大多數時候我們實際上都在嘗試編寫代碼,因此對於您和下一個程序員來說這是可以理解的。 快速超速是一個次要問題(警惕過早優化)。
當Labels(和goto)被濫用時,它們會使代碼的可讀性降低,這會讓您和下一位開發人員感到悲傷。 編譯器不關心。
您很少需要標簽,因為它們很少使用,所以很容易混淆。 但是,如果您需要使用一個,請使用一個。
BTW:這個編譯並運行。
class MyFirstJavaProg {
public static void main(String args[]) {
http://www.javacoffeebreak.com/java101/java101.html
System.out.println("Hello World!");
}
}
我很想知道你對標簽的替代品是什么。 我認為這幾乎可以歸結為“盡早返回”與“使用變量保持返回值,最后只返回”的論點。
當您有嵌套循環時,標簽是非常標准的。 他們真正降低可讀性的唯一方法是,其他開發人員以前從未見過它們並且不理解它們的含義。
我認為通過新的for-each循環,標簽可以非常清晰。
例如:
sentence: for(Sentence sentence: paragraph) {
for(String word: sentence) {
// do something
if(isDone()) {
continue sentence;
}
}
}
我認為通過讓你的標簽與新的for-each中的變量相同,我看起來非常清楚。 事實上,也許Java應該是邪惡的,並為每個變量添加隱式標簽
我使用Java標記的循環來實現Sieve方法來查找素數(為項目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個嵌套循環,並且對於某些條件,您希望返回到最外層循環。
所以他們有自己的用途,這取決於你試圖解決的問題。
我從來沒有在Java代碼中看到過“野外”使用過的標簽。 如果你真的想要突破嵌套循環,看看你是否可以重構你的方法,以便早期的return語句能夠達到你想要的效果。
從技術上講,我猜早期退貨和標簽之間沒有太大區別。 但實際上,幾乎每個Java開發人員都看到了早期的回報,並知道它的作用。 我猜許多開發人員至少會對標簽感到驚訝,可能會感到困惑。
我在學校教過單入/單出正統,但我已經開始欣賞早期的返回語句和斷開循環,以簡化代碼並使其更清晰。
我在某些地方支持它們,我發現它們在這個例子中特別有用:
nextItem: for(CartItem item : user.getCart()) {
nextCondition : for(PurchaseCondition cond : item.getConditions()) {
if(!cond.check())
continue nextItem;
else
continue nextCondition;
}
purchasedItems.add(item);
}
我從不在代碼中使用標簽。 我更喜歡創建一個后衛並將其初始化為null或其他異常值。 這個守衛通常是一個結果對象。 我沒有看到我的同事使用標簽,也沒有在我們的存儲庫中找到任何標簽。 這真的取決於你的編碼風格。 在我看來,使用標簽會降低可讀性,因為它不是一個常見的結構,通常它不會在Java中使用。
是的,你應該避免使用標簽,除非有特定的理由使用它們(簡化算法實現的例子是相關的)。 在這種情況下,我建議添加足夠的評論或其他文檔來解釋其背后的推理,以便有人不會在以后出現並將其從“改進代碼”或“擺脫代碼味道”的概念中刪除或其他一些潛在的BS借口。
我會把這類問題等同於決定何時應該或不應該使用三元組。 主要理由是它可能妨礙可讀性,除非程序員非常小心地以合理的方式命名,否則使用標簽之類的約定可能會使事情變得更糟。 假設使用'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庫只是建立在這個功能的基礎上來宣布它的測試階段。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.