2011-11-16 64 views
19

Chương trình sau đây không có tầm quan trọng của riêng nó. Nó chỉ đếm số đối tượng được tạo thông qua việc sử dụng vòng lặp for bằng cách sử dụng một trường tĩnh bên trong lớp Counter như được hiển thị bên dưới.Câu lệnh tạo đối tượng trong Java không cho phép sử dụng vòng lặp một dòng. Tại sao?

package temp; 

final class Counter 
{ 
    private static int cnt; 

    public Counter() 
    { 
     cnt++; 
    } 

    public static int show() 
    { 
     return(cnt); 
    } 
} 

final public class Main 
{ 
    public static void main(String[] args) 
    { 
     for (int i=0;i<50;i++) 
     { 
      Counter counter=new Counter(); 
     } 

     /*for (int i=0;i<50;i++) 
      Counter counter=new Counter();*/ 

     System.out.print("\nNumber of objects constructed:->"+Counter.show()+"\n\n"); 
    } 
} 

Câu hỏi duy nhất ở đây là nhận xét vòng lặp for có nghĩa tương tự như trên cho vòng lặp (điều tương tự cũng được áp dụng cho một vòng lặp while) không làm việc ở tất cả gây ra một compile- lỗi thời gian cho biết rằng "không phải là tuyên bố" có nghĩa là trong trường hợp cụ thể này, cặp dấu ngoặc là bắt buộc mặc dù vòng lặp for chỉ chứa một câu lệnh! Tại sao?

Trả lời

27

Để hiểu tại sao điều này xảy ra, bạn phải nhìn vào Java's Blocks and Statements syntax trong đặc tả ngôn ngữ.

Một ForStatement được định nghĩa là:

ForStatement: 
    for (ForInitopt ; Expressionopt ; ForUpdateopt) 
     Statement 

Tuyên bố được định nghĩa là:

Statement: 
    StatementWithoutTrailingSubstatement 
    LabeledStatement 
    IfThenStatement 
    IfThenElseStatement 
    WhileStatement 
    ForStatement 

StatementWithoutTrailingSubstatement: 
    Block 
    EmptyStatement 
    ExpressionStatement 
    SwitchStatement 
    DoStatement 
    BreakStatement 
    ContinueStatement 
    ReturnStatement 
    SynchronizedStatement 
    ThrowStatement 
    TryStatement 

Sau đó, nhìn vào Block:

Block: 
    { BlockStatementsopt } 

BlockStatements: 
    BlockStatement 
    BlockStatements BlockStatement 

BlockStatement: 
    LocalVariableDeclarationStatement 
    ClassDeclaration 
    Statement 

Bạn sẽ nhận thấy rằng, trong vòng này đặc tả, LocalVariableDeclarationStatement không hợp lệ trừ khi nó nằm trong một khối. Tuy nhiên, vì ForStatement yêu cầu rằng nó được theo sau bởi một câu lệnh, phải tồn tại dấu ngoặc đơn để làm cho biểu thức hợp lệ. Như vậy, bất kỳ khai báo biến cục bộ nào sẽ không hợp lệ trong vòng lặp mà không có dấu ngoặc.

+1

+1 để đào nó ra khỏi JLS. –

+2

JasCav có quyền. Một tuyên bố khai báo không giống như một câu lệnh bắt buộc chuẩn, và không thể đứng một mình như một vòng lặp (và có thể không phải là phần thân của if/else). –

6

Vì bạn đang tạo biến phạm vi. Java đang nói với bạn rằng điều này không có gì bởi vì tất cả nó làm là cấp phát bộ nhớ và ngay sau khi vòng lặp đi qua một lần nữa bạn sẽ mất một cái và tạo một cái mới. Về cơ bản toàn bộ vòng lặp là một NOP đó là lý do tại sao nó nói với bạn rằng nó làm giảm một tuyên bố không làm gì.

Do vòng lặp là NOP, nghĩa là khai báo trong vòng lặp là NOP.

Lý do phiên bản có niềng răng hoạt động là do trình biên dịch không kiểm tra việc sử dụng trong phạm vi vì có dấu ngoặc ôm. Nó có thể là một cái gì đó để làm với cây phân tích cú pháp tạo ra từ một tuyên bố dòng so với cây phân tích được tạo ra khi có một phạm vi vòng lặp đầy đủ.

+2

+1 Để rõ ràng hơn, đó là vì trình biên dịch * biết * bạn không làm gì trong trường hợp thứ hai và cho bạn biết. Trong lần đầu tiên nó không. –

+2

Điều đó không đúng. Hàm khởi tạo tăng một bộ đếm tĩnh, vì vậy 'new Counter()' có các tác dụng phụ và không phải là NO-OP –

+0

@BrianRoach Cảm ơn bạn đã xóa nó.Tôi chưa bao giờ viết một trình biên dịch cho một ngôn ngữ OOP nhưng tôi đoán rằng có ý nghĩa như một câu lệnh dòng không cần phạm vi phức tạp hơn trong khi các vòng lặp với nhiều câu lệnh yêu cầu độ phân giải biểu tượng khác nhau. –

4

@JasCav là đúng, tuy nhiên bạn có thể lấy nó để biên dịch:

for (int i=0;i<50;i++) 
    new Counter(); 
+0

Đúng, điều này hoạt động bởi vì nó không phải là một tuyên bố. –

4

Bạn cũng có thể lấy nó để làm việc mà không cần niềng răng theo cách này:

Counter counter; 
    for (int i = 0; i < 50; i++) 
    counter = new Counter(); 

Không phải là có bất kỳ lý do nào bao giờ bạn muốn làm một điều như vậy. Rời khỏi các dấu ngoặc vuông là một ý tưởng không thực sự thực sự là vì việc thêm tuyên bố thực sự làm thay đổi luồng điều khiển.

+0

+1 để rời khỏi niềng răng là một ý tưởng tồi. Tương tự cho các câu lệnh if. Chỉ làm điều đó nếu bạn sẽ đặt "cơ thể" trên cùng một dòng như cho/nếu như là một loại tín hiệu cho những gì bạn đã làm. –

Các vấn đề liên quan