Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I received a compilation error for the following code:

if(true)
    int a = 10;
else
    int b = 20;

If I change it to the following code, then there is no compilation error:

if(true) {
    int a = 10;
}
else {
    int b = 20;
}

Why is the first syntax wrong, and from what language standard?

share|improve this question
5  
It isn't wrong. What error did you get? –  Daniel 19 hours ago
6  
You do realize that you're compiling with C++ and not Java, right @Daniel? –  Makoto 18 hours ago
1  
After doing some testing, it seems JVM doesn't like having variable declarations inside an if-else without braces. I'm sure someone could go more in-depth with this, but my guess is the scope can't be resolved. System.out.println() works without braces. –  Drew Kennedy 18 hours ago
2  
@Makoto Oops didn't realize the question was Java –  Daniel 18 hours ago
2  
@Daniel I was just thinking that too. If you're allowed only one line of code after the if, declaring a variable wouldn't make sense. –  Drew Kennedy 18 hours ago

5 Answers 5

up vote 11 down vote accepted

The Java specification says that an if-then-else statement is of the following form:

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

Where Statement and StatementNoShortIf can be various things including blocks (code surrounded with braces), assignments (to already declared variables), other if statements etc.

Of note is that declaration statements (e.g. int a; or int a = 10;) are missing from that list, thus you get a compilation error.

For the full list, you can read the Java specification here: http://docs.oracle.com/javase/specs/

share|improve this answer
2  
This should be enough to answer the question, just a little bit surprise for a c++ programmer with this kind of error. –  Orup 12 hours ago
    
And with the answer in 'A single-line loop with a mandatory pair of braces in Java' should make it clear enough to the question. –  Orup 12 hours ago
    
What does NoShortIf refer to? –  Navin 3 hours ago
1  
@Navin The NoShortIf is to prevent situation with nested if statements where a reader of the code cannot easily decide (or might get confused) to which if an else branch belongs to. This is explained in section 14.5 of the Java Language Specification –  Mark Rotteveel 3 hours ago
    
@MarkRotteveel Nifty! –  Navin 2 hours ago

JLS-14.4. Local Variable Declaration Statements reads (in part),

Every local variable declaration statement is immediately contained by a block.

And

JLS-14.9. If Statmenets

Otherwise, execution continues by making a choice based on the resulting value:

If the value is true, then the contained Statement is executed; the if-then statement completes normally if and only if execution of the Statement completes normally.

If the value is false, no further action is taken and the if-then statement completes normally.

However, JLS-14.5. Statements doesn't include variable declaration.

Defining two different variables within the scope of a single-statement block (containing just the variable definitions) makes them both unreachable. I think you'd have better luck with a ternary expression

int a = (condition) ? 10 : 20;

or

int a;
if (condition)
    a = 10;
else
    a = 20;

or

int a;
if (condition) {
    a = 10;
} else {
    a = 20;
}

Note that the variable a is then initialized to a value based on the condition and it is reachable after that statement.

share|improve this answer
1  
I disagree with your assessment "So your first example creates a block for int a which terminates the if block (and thus your else has no matching if)." The reason is the definition of statement and block in the JLS –  Mark Rotteveel 18 hours ago
1  
@MarkRotteveel is right. The error has nothing to do with the else. If you take out the else part you still get an error. –  ajb 18 hours ago
    
@Mark Edited. Thanks for your input, do you think it reads better now? –  Elliott Frisch 18 hours ago
    
And if it were allowed, how would you reach it? Hence, I think, why it isn't allowed. –  Elliott Frisch 18 hours ago
1  
I removed my earlier comment, you are entirely right with your last edit; I was approaching it too much from the syntax point of view, and not from the reasons for that syntax. –  Mark Rotteveel 18 hours ago

Lets analyze what your first code example would mean for the language design

if(condition)
    int a = 10;
else
    int b = 20;

Either it means that depending on the condition we have defined a or b. As we don't know which branch was taken, how do we use either a or b after the if-statement? We can't (and if we could that would probably result in strange bugs).

So as language designers we decide that a and b are not visible outside their respective branches to avoid these weird bugs. But as a block-less branch can only have a single statement, we have declared a (or b) only to be immediately unreachable/unusable again, so doing that makes no sense. Therefor we decide that a variable declaration is only allowed with a block. A block can have multiple statements, so variables declared in that block can be used by those other statements.

The designers of Java probably applied similar reasoning, so they decided to only allow declaration in a block. This is done through the definition of if (JLS 14.9):

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

Statement (JLS 14.5)

Statement:
    StatementWithoutTrailingSubstatement
    ...

StatementNoShortIf:
    StatementWithoutTrailingSubstatement
    ...

StatementWithoutTrailingSubstatement:
    Block
    ...

Block (JLS 14.2):

Block:
    { [BlockStatements] }

BlockStatements:
    BlockStatement {BlockStatement}

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement

And LocalVariableDeclarationStatement (JLS 14.4), which repeats that it can only occur within a immediately enclosing block:

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.

share|improve this answer

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.

Read this http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.4

share|improve this answer
    
Except that the second version does compile –  Juan Mendes 18 hours ago
3  
@JuanMendes The second version is immediately contained in a block. –  Mark Rotteveel 18 hours ago
    
yes that is the reason –  Lalith Jayasinghe 18 hours ago

My best guess is that you cannot declare variables conditionally.

  • When you don't have braces, you're trying to declare a variable conditionally in the outer scope, that's not allowed.
  • When you add the braces, you're creating the variables in that local scope (which are not allowed to be used outside of those braces)
share|improve this answer
1  
I know this is probably not accurate, I'd love for someone to explain what the problem with the answer is. –  Juan Mendes 18 hours ago
    
this answer is helpful to me. –  Grijesh Chauhan 4 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.