Why do I need brackets here? Java: “if (true) int

2019-04-29 18:14发布

问题:

public class Test{
   public void newMethod(){

      if(true)int i=0;

   }
}

The above code gives me the following error

Test.java:4: error: '.class' expected
      if(true)int i=0;
                  ^

But if I write it like this

public class Test{
   public void newMethod(){

      if(true){
         int i=0;
      }

   }
}

then there is no error!

I know this question isn't helpful to the community, but I'm really curious why I need to have brackets in this statement. I've been programming in java for a few years and I've only encountered this error just now.

I'm using JGrasp by the way.

回答1:

Here is my understanding. Quoting from Chapter 14 of JAVA SE 7 specification:

14.2. Blocks

A block is a sequence of statements, local class declarations, and local variable declaration statements within braces.

Block:
    { BlockStatementsopt }

........     

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement

So a block is always in braces { ... }.

14.4. Local Variable Declaration Statements

A local variable declaration statement declares one or more local variable names.

LocalVariableDeclarationStatement:
    LocalVariableDeclaration ;

LocalVariableDeclaration:
    VariableModifiersopt Type VariableDeclarators

.......

VariableDeclarator:
    VariableDeclaratorId
    VariableDeclaratorId = VariableInitializer

.......

Every local variable declaration statement is immediately contained by a block. Local variable declaration statements may be intermixed freely with other kinds of statements in the block.

Now, what does it mean, "immediately contained"?

Some statements contain other statements as part of their structure; such other statements are substatements of the statement. We say that statement S immediately contains statement U if there is no statement T different from S and U such that S contains T and T contains U. In the same manner, some statements contain expressions (§15) as part of their structure.

Let's look at your example:

public class Test{
   public void newMethod(){

      if(true)int i=0;

   }
}

In this case we have the following block:

{

          if(true)int i=0;

}

Inside this block we have an If Statement:

if(true)int i=0;

This statement, in turn, contains a local variable declaration:

int i=0;

Therefore, the condition is violated. Recall: Every local variable declaration statement is immediately contained by a block. However, in this case the local variable declaration is contained by an If statement, which is not a block itself, but is contained by another block. Hence this code would not compile.

The only exception is for a for loop:

A local variable declaration can also appear in the header of a for statement (§14.14). In this case it is executed in the same manner as if it were part of a local variable declaration statement.

(You may need to reread it a few times to understand.)



回答2:

Dark Falcon is right, if a single statement following an if test is a variable declaration then nothing can use that variable, the declaration would be limited in scope to the body of the if consequent, which would be useless, because anything following that would not have i in scope.

If if (true)int i = 0; actually worked (meaning the declaration was visible to succeeding lines), that would mean that whether you had a variable declared would depend on the result of the if test, which would not be good.

BTW, if (true) int i = 0; causes this syntax error in Eclipse:

Multiple markers at this line
    - i cannot be resolved to a variable
    - Syntax error on token "int", delete 

while putting the brackets around it compiles, although it generates a warning:

the value of the local variable i is not used