[英]Semicolon at end of 'if' statement
今天找了半個小時的bug,發現可以在if語句后加分號代替代碼,像這樣:
if(a == b);
// Do stuff
這基本上意味着無論a
是否等於b
都會執行這些操作,並且if
語句沒有任何意義。 為什么Java不給我一個錯誤? 在任何情況下這會有用嗎?
在任何情況下這會有用嗎?
有用? 比如“讓你的代碼更干凈、更清晰、更快、更易於維護”? 一點也不。 這很可能是糟糕的、令人困惑的代碼。
但這不一定是良性的。 由於導致副作用的方法,這樣的語句可以執行操作和/或更改狀態,並且可選地評估由於操作符的短路而導致的這些方法。
if( a() && b() );
這里, a()
或b()
可能會做某事,而b()
只會在a()
為真時執行。
至於為什么,我認為答案很簡單,偏離定義的、預期的行為(例如while(reader.read());
類的語句)比開發人員編寫錯誤代碼的替代方案更糟糕。
編寫糟糕的代碼總是可能的。 重申一下,這幾乎在任何情況下都是糟糕的代碼。
一個可能的用例:
if (a==b);
else {
// Do something
}
不好,但有可能。
不過,我確實認為 Java 規范應該禁止空的if
。
如果您使用的是 Eclipse,您可以讓它警告您這些語句:
如果使用if
語句,則if
后的第一條語句將在條件為真時執行。 如果在if
之后有一個塊(帶花括號),則它計入整個塊。 如果沒有塊,它只計算一個語句。 單個分號是一個空語句。 你也可以從你的例子中編寫代碼,如下所示:
if(a==b) {
;
}
這是一個古老的遺留物,當時有更多的語法糖來區分表達式和語句。
基本上,逗號用作列表項分隔符,因此分號用作“語句列表”分隔符。 缺點是處理列表中的空項目和塊中的空語句。
在項目列表中,Java 使用顯式關鍵字null
,但“空語句”只是一個空行。 允許存在空行是繼承自 C 的傳統的延續。
為什么要這樣做? 特別是當您知道沒有正在執行任何語句時使用if
語句:因為某些 if 語句有副作用:
int c;
if ((c = in.read()) != -1);
是的,這不是最好的例子,但基本上它說從流中讀取一個字節並且什么都不做。 在某些極端情況下可能很有用,但即使這個例子不是最好的,它也說明了意圖。 我們希望在不意外執行任何語句的情況下感受表達式的副作用。
我想不出它有用的場合。 它對於像這樣的循環很有用
while(do something);
或者
for(init; do something; something else);
如果您經常在 IDE 中使用代碼格式,這些類型的錯誤就會變得很明顯。 一些 IDE 也強調這是一個可能的錯誤。
我同意你的看法,這對人類沒有任何用處。 我懷疑它在那里是因為它簡化了語言定義; 例如,這意味着在if
之后出現的事物與在一段while
之后出現的事物相同。
為什么? 這是因為它對編譯器編寫者來說更容易。 您不必在if(cond)
之后做一個特殊情況來檢查分號,並且增加了允許的用法
if (cond && maybeFunc())
;// Code here I want to ignore
盡管允許這樣做實際上是一個糟糕的主意。 允許然后添加一個案例來檢查這個更容易。
Java 允許在任何允許使用語句塊的地方使用空塊。 我確信將其作為所有塊的一般規則會簡化編譯器。
我同意這主要是導致異常難以找到的錯誤的原因。 我總是在塊周圍使用大括號,即使只有一個語句,但 Java 允許你在任何時候用大括號創建一個塊,所以使用大括號不能讓你免於這種命運。 例如,我曾經浪費了 4 個小時試圖找到這樣的東西:
while (condition);
{
statement;
statement;
}
第一行末尾的分號是一個錯字,不小心使 while 循環的語句塊為空。 因為語法有效,程序編譯並運行良好,只是不是我想要的方式。 真的很難找到。
我可以想到一種情況,允許你有空塊是非常好的,這是這樣的:
if (condition1) {
do_action_1();
}
else if (condition2) {
//nothing really to do in this case
}
else if (condition3) {
do_action2();
}
else {
do_action3();
}
在上面的示例中,您希望能夠分離出各種條件。 請記住,這些條件可能會重疊,因此並不總是可以重新排列順序。 如果其中一個條件確實不需要做任何事情,那么 Java 允許您擁有一個空塊是件好事。 否則,當你真的不想做任何事情時,語言將需要某種形式的“noop”方法來使用。
我個人更喜歡顯式的“noop”語句——但這不是 Java 的定義方式。
只是關於可用性的僅供參考,如果有這樣的聲明,它會產生或可以產生什么不同
考慮如下一段代碼。
int a = 10;
if ((a = 50) == 50);
System.out.println("Value of a = " + a);
很明顯,在這種情況下, if
語句確實改變了輸出。 因此,這樣的聲明可能會有所作為。
在這種情況下,這可能是有用的,或者說對程序有影響更好。
if(a==b)
println("a equals b");
如果只有一行要執行,您可以使用不帶{}
的 IF 語句,因此使用if(a==b);
你是說如果它們相等,執行和空語句......所以它什么都不做,然后返回到你的正常循環,在 IF 塊之外。
jls 中的一些定義解釋了這一點(第 14 章):
正如此處所述,一個Block
是一個StatementWithoutTrailingSubstatement
,而后者又是一個StatementNoShortIf
,它是一個Statement
。 因此,無論何時需要這些,我們都可以插入一個Block
。
盡管for
和while
循環也是如此,但我將使用if
語句。 這些規則幾乎相同。 可以在此處找到if-statements
的句法描述。
IfThenStatement:
if ( Expression ) Statement
IfThenElseStatement:
if ( Expression ) StatementNoShortIf else Statement
IfThenElseStatementNoShortIf:
if ( Expression ) StatementNoShortIf else StatementNoShortIf
所以我們可以在這里使用我們的塊。
;
被定義為EmptyStatement
( link ),它也是StatementNoShortIf
。 因此,在條件代碼段中,例如if-statement
和循環,如果需要StatementNoShortIf
或Statement
,我們可以將Block
替換為EmptyStatement
。
因此if(Expression)EmptyStatement
有效。
很簡單:如果發現無效語法,java 會報錯。 但是if(Expression)EmptyStatement
是完全有效的語法。 相反,如果使用正確的參數啟動, javac
會發出警告。 為此,可以禁用/啟用的完整警告列表將警告名稱列為empty
。 因此,使用-Xlint:all
或-Xlint:empty
編譯將生成關於此的警告。
您的 IDE 也應該有一個選項來啟用這種警告。 對於日食,請參閱@nullptr 的回答。 在 IntelliJ 中,您可以按Ctrl + Shift + A
,在搜索字段中輸入empty body
並啟用警告(在圖像中標記)
老實說,從極簡主義的角度來看,它沒有多大用處。 通常有一種方法可以在沒有“什么都不做”命令的情況下完成任務。 這是個人喜好的問題,您是否更願意使用
if( a() && b() );
或者
if( a() ) b();
同樣適用於使用EmptyStatement
其他情況。 在這個主題上需要考慮的一個重點是代碼的可讀性。 在某些情況下,通過使用 no-op,代碼變得更具可讀性。 另一方面,在某些情況下,使用EmptyStatement
代碼變得更加難以理解 - 上面的示例將計入后來的 IMO。
我可以想到一個需要空語句的場景(不是用於if
條件而是用於while
循環)。
當程序只需要用戶的明確確認以繼續時。 當用戶確認后的工作取決於其他一些事情並且用戶想要控制何時繼續時,這可能是必需的。
System.out.println("Enter Y to proceed. Waiting...");
System.out.println("");
while(!(new Scanner(System.in).next().equalsIgnoreCase("Y")));
System.out.println("Proceeding...");
// do the work here
看看這個:
int a,b,c = 0;
if(a == b){
c =1;
}
System.out.print(c);//1
所以,你可以這樣寫:
if (a == b)c=1;
但是,如果這段代碼是這樣的:
int a,b,c=0;
if (a != b){
}
if (a == b ){
c =1;
}
你可以這樣寫:
if(a != b);
if(a == b )c=1;
所以,你會知道if(a != b);
做注意
if 中的分號表示 if 條件的終止,如 java 中一樣;
被視為語句的結束,因此執行 if 之后的語句。
結尾的分號,
如果(a==b); 只需在單行中完成語句,這意味着忽略條件的結果並從下一行繼續執行
這段代碼很有用,另一方面有時會在程序中引入錯誤,例如,
情況1。
一 = 5;
b = 3;
如果(a == b);
prinf("a 和 b 相等");
情況二。
一 = 5;
b = 5;
如果(a == b);
prinf("a 和 b 相等");
會在屏幕上打印相同的輸出...
在為班級進行編程作業時,我正在使用 N x N 網格裝飾品並將隨機裝飾品的特征與上方、下方、左側和右側的特征進行比較,我發現它的一個很好的用途是防止嵌套語句和潛在的邊界例外。 我的目標是最小化代碼並避免嵌套 if 語句。
if (row == 0);
else (method (grid[row][col], grid[row-1][col]));
if (row == N-1);
else (method (grid[row][col], grid[row+1][col]));
if (col == 0);
else (method (grid[row][col], grid[row][col-1]));
if (col == N-1);<br>
else (method (grid[row][col], grid[row][col+1]));
其中method(Doodad a, Doodad b)
在 a 和 b 之間做一些操作。
或者,您可以使用異常處理來避免這種語法,但它適用於我的應用程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.