Monday, March 08, 2021

Variable declaration inside if statement

Took a while for me to figure this out... 

Consider the below piece of code

public class Main {

    public static void main(String[] args) {

        boolean flag = true;
        
        if(flag)
            String message = "I will not compile";
        
        if(flag) {
            String message = "Here I am ok...";
        }
    }
}

In this code, the first if statement does not compile. Second if statement is all fine. 

Only difference here is 

- in the first there are no curly braces surrounding the if statement. 

- in the second one, we have the curly braces surrounding the if statement.

Compiling this code throws the error message "variable declaration not allowed here"

Main.java:7: error: variable declaration not allowed here
                        String message = "I will not compile";

So the variable declaration is not allowed inside the if statement, when it is not surrounded by curly braces.

But why is the variable declaration not allowed when we do not have curly braces? 

Is it not perfectly fine to avoid curly braces when we have only one statement inside the if block?

The first reason I could think of is: 

Variable declaration and value assignment to that variable are considered as two statements by the compiler though its declared in a single line. Since only one line is allowed inside of an if statement when its not surrounded by braces, the compiler rejects it. 

This argument made some sense, but then why not the compiler just take the 1st statement as contained within the if block and the 2nd as contained outside of the if block even when variable declaration and value assignment are considered as two separate statements?

This doesn't make sense as then we have variable declaration inside of the if block and assignment of value to that variable outside of if block where that variable is not visible.  

So the compiler rejecting the code for the reason that a single line of code like 

String message = "I will not compile";

actually represents two statements as shown below is on expected lines.

String message;
message = "I will not compile";

Except for one catch. What if we only do variable declaration inside the if block, that is not surrounded by braces. 

Of course that variable will not be of any use. But so is the case of our original example - declaring a variable and assigning a value to it is as well of no use, unless it is used somewhere isn't it?

So lets try that out

public class Main1 {

    public static void main(String[] args) {

        boolean flag = true;
        
        if(flag)
            String message; // Compilation error here
        
        if(flag) {
            String message; // Allowed
        }

    }
}

We have made the statement inside if block as atomic as possible - having only a variable declaration without assigning any value to it. But here again, the one without curly braces throws compilation error while the other with curly braces compiles fine.  

OK... Time for some searching around...

And it turns out that the scope of a variable declared within if statement not surrounded by braces - is the scope in which if statement itself is (i.e, the surrounding scope of the if statement). 

Since the variable is declared conditionally - that the variable will be defined if and only if the if statement evaluates to true (too many if's... :)). This variable is not guaranteed to be available in the surrounding scope in all scenarios. Hence the compiler does not allow this statement and throws an error.

And for the same reason, variable declaration is not allowed in looing statements as well, when the body of the statement is not surrounded by curly braces. 

Below code shows all the error scenarios

public class Main2 {

    public static void main(String[] args) {

        boolean flag = true;
        
        if(flag)
            String message = "I will not compile";
        
        for(; flag ;)
            String message = "I will not compile";
            
        while(flag)
            String message = "I will not compile";
    }
}


Sample code used in this post can be downloaded from https://github.com/ashokkumarta/awesomely-java/tree/main/2021/03/Curious-Cases/Variable-declaration-inside-if-statement

No comments:

Post a Comment