1. 程式人生 > >if後面只有一句話,該不該加大括號?

if後面只有一句話,該不該加大括號?

原則上,for迴圈和if語句如果後面跟著只有一句話,是可以不加的,但是為了程式碼安全和良好的變成習慣,還是加上好。原因如下:

文章地址   http://blog.csdn.net/java2000_net/article/details/2835995

看上去一個很簡單的問題,結果卻不是想象中的那樣。良好的編碼習慣是多麼的重要啊

原文地址:http://topic.csdn.net/u/20080825/18/34F53E23-ECBC-4A91-B8B5-8C7F2A07F50A.html

測試的程式碼如下

  1. publicclass TestPrintStream1 {
  2. publicstaticvoid main(String[] args) {
  3.     Class c = TestPrintStream1.class;
  4. try {
  5.       Object o = c.newInstance();
  6. if (o instanceof TestPrintStream1)
  7.         TestPrintStream1 tt = (TestPrintStream1) o;// 這裡為什麼會報錯呢,說tt 和 TestPrintStream1不能不解析
  8.     } catch (InstantiationException e) {
  9.       e.printStackTrace();
  10.     } catch (IllegalAccessException e) {
  11. // TODO Auto-generated catch block
  12.       e.printStackTrace();
  13.     }
  14.   }
  15. }

那一行為什麼會報錯呢?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時會假設後面應該是個表示式之類或語句,而宣告不是關鍵字,所以它報出無法解析。
  1. if (true)
  2. new Object();
並不報錯。 但是
  1. if (true)
  2. int a;
  3. if (true)
  4. 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迴圈也一樣。