if後面只有一句話,該不該加大括號?
阿新 • • 發佈:2019-02-08
原則上,for迴圈和if語句如果後面跟著只有一句話,是可以不加的,但是為了程式碼安全和良好的變成習慣,還是加上好。原因如下:
文章地址 http://blog.csdn.net/java2000_net/article/details/2835995
看上去一個很簡單的問題,結果卻不是想象中的那樣。良好的編碼習慣是多麼的重要啊。
原文地址:http://topic.csdn.net/u/20080825/18/34F53E23-ECBC-4A91-B8B5-8C7F2A07F50A.html
測試的程式碼如下:
- publicclass TestPrintStream1 {
-
publicstaticvoid main(String[] args) {
- Class c = TestPrintStream1.class;
- try {
- Object o = c.newInstance();
- if (o instanceof TestPrintStream1)
- TestPrintStream1 tt = (TestPrintStream1) o;// 這裡為什麼會報錯呢,說tt 和 TestPrintStream1不能不解析
- } catch (InstantiationException e) {
- e.printStackTrace();
-
} catch (IllegalAccessException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
那一行為什麼會報錯呢?if語句後面不是允許不加大括號嗎?
2樓 java2000.net
if ()
後面不使用花括號時,裡面不能出現宣告,因為那個涉及到作用域,而沒有花括號又沒有作用域了。
個人理解。
boolean ok = true;
if(ok)
MyClass c = new MyClass();
這樣也是不允許的。
改成
MyClass c = null;
if(ok)
c = new MyClass();
這樣是可以的
這個程式碼問題和 instanceof 沒有任何關係
6樓 segazk
Java 把 Test tt = new Test(); 當兩條語句看待了相當於 Test tt; tt = new Test();
Eclipse 中報的語法錯誤是:
Test cannot be resolved tt cannot be resolved
cmd 下 javac 沒通過編譯報的錯誤是:
D:/Test.java:x: 不是語句
Test tt =new Test();
^ D:/Test.java:x: 需要 ';'
Test tt =new Test();
^2 錯誤
Java Language Specification 明確指出區域性變數宣告的作用範圍是在一個
塊內,也可以理解為在“{ }”內。for 迴圈可以不使用“{ }”的,但僅限於
執行語句(其中並不包括變數宣告語句)
我們看到的程式碼是這樣的:
01 public class TestPrintStream1 {
02
03 public static void main(String[] args) {
04
05 Class c = TestPrintStream1.class;
06 try {
07 Object o = c.newInstance();
08 if (o instanceof TestPrintStream1)
09 TestPrintStream1 tt = (TestPrintStream1) o;
10 } catch (InstantiationException e) {
11 e.printStackTrace();
12 } catch (IllegalAccessException e) {
13 e.printStackTrace();
14 }
15 }
16 }
由於變數作用域的關係,編譯器所看到的程式碼是這樣的,注意 09 行的縮排!
01 public class TestPrintStream1 {
02
03 public static void main(String[] args) {
04
05 Class c = TestPrintStream1.class;
06 try {
07 Object o = c.newInstance();
08 if (o instanceof TestPrintStream1)
09 TestPrintStream1 tt = (TestPrintStream1) o;
10 } catch (InstantiationException e) {
11 e.printStackTrace();
12 } catch (IllegalAccessException e) {
13 e.printStackTrace();
14 }
15 }
16 }
從 08 和 09 行編譯器所理解的程式碼中來看,很明顯 08 行的 if 語句並沒有
結束,因此編譯器會認為 if 後面少掉一個語句結束的分號。
笨笨地編譯器猜想你的程式碼應該是這樣的,注意 08 行後面的分號
08 if (o instanceof TestPrintStream1);
09 TestPrintStream1 tt = (TestPrintStream1) o;
實際上編譯器的這種理解並不是我們想要的。
為了不出現我們所不知的東西來困擾,應該老老實實地在 for, if, while 等語句後面加
上 { },哪怕塊中的語句只有一行。
各位,這裡有沒有熟悉C語言的朋友,相信大家都知道,在C語言裡,變數的宣告都是要出現在作用域的第一條非賦值語句前的。所以java也是c風格的語言, 它也可能有類似的很細節的規則,就是,java的變數宣告必須是一條語句。而java的每個作用域裡面的語句分割符是“;”,if (true) statemenet;只是一條語句,並且如12樓所說,javac提示缺少;,因為它認為宣告是一條新語句,而這裡卻不是。另一個方面javac在解析 到單行if時會假設後面應該是個表示式之類或語句,而宣告不是關鍵字,所以它報出無法解析。
- if (true)
- new Object();
- if (true)
- int a;
- if (true)
- int a=3;
接觸過vb的朋友也知道,vb有塊if語句和行if語句,雖然java沒有明確提到,但是if (true) statemenet;就是行if語句。行內的作用域與if所在作用域相同。因為作用域是由{}決定的。只是lz提到的問題很難碰到(如果嚴格參考 java規範的化),所有平時也沒人會去考慮。當然我無法證明這個作用域究竟是什麼!
這是我的理解。
try {
Object o = c.newInstance();
if (o instanceof TestPrintStream1)
{
TestPrintStream1 tt = (TestPrintStream1) o;
}
}這樣很明確,tt的作用域在if(){}的{}內({}是塊作用域的標誌)所以程式沒有問題,而:
try {
Object o = c.newInstance();
if (o instanceof TestPrintStream1)
TestPrintStream1 tt = (TestPrintStream1) o;
}編譯器在編譯這段程式碼時,當編譯到TestPrintStream1 tt = (TestPrintStream1) o;時,會確定tt的作用域是在try{}的{}中。這明確幾點,編譯器在編譯if語句時,並不對if語句表示式的對錯作出判斷,程式在執行時才對if語 句表示式的對錯做判斷。還有就是編譯器編譯程式碼是順序編譯的。(這都是編譯原理中的知識,這裡要用到這些知識來解決這個問題)當編譯器編譯 TestPrintStream1 tt = (TestPrintStream1) o;時,編譯器不能確定是否會生成tt物件(因為if語句表示式的對錯沒有確定)並且編譯器不能確定這句後是否會用到tt物件。這樣就有可能出現:tt對 象沒有生成(if表示式錯),而在TestPrintStream1 tt = (TestPrintStream1) o;的後面又要用到tt物件,這樣程式會出錯,也可能出現其他其他三種情況。但這已經不重要了,因為有了這種情況,tt的定義已經出現了歧義,所以編譯器 無法編譯。這有很多解決方法。
在做些說明:像以上的程式碼形式,
{
int j = 0;
if (j == 0)
int i = 1;
}
在C、 c++ 和C#中都是正確的,即使在Vs2005中這樣的Java程式碼也是正確的,因為這種形式的程式碼在不同的編譯方法中會有不同的解釋(比如這樣的形式 i 的作用域被預設為與if(){}形式中的一樣。那麼這樣的形式就會正確)。從這可以看出,1、編寫程式碼時,儘可能的與規範靠攏,2.熟悉自己用得編譯器
總結:
為了我們的程式碼安全,養成良好的編碼習慣,及時if後面只有一個語句,我們也要加上大括號,for迴圈也一樣。