12

I made a coding mistake while working on an application, it was a test for null reference. It took me hours to discover what the issue was, but what i don't understand is why the code behaved this way.

String name = null;
String value = null;

if(name != null && value != null);
{
    System.out.println("Values not null");
}

The if Statement ended with ;, that was my mistake and the Values not null was printed even when it is obvious that both values are null. Can anybody explain why?

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
Uchenna Nwanyanwu
  • 3,174
  • 3
  • 35
  • 59

9 Answers9

14

This semicolon ends a statement (an empty one), so your code is translated by the compiler to something like this:

if(name != null && value != null)
{
  //nothing here
}
{
  System.out.println("Values not null");
}

In other words, if if expression is true, it executes empty block of code. Then no matter whether if was true or not, the runtime proceeds and runs the block containing System.out. Empty statement is still a statement, so the compiler accepts your code.

Another place where such a mistake can happen:

for(int i = 0; i < 10; ++i);
{
  System.out.println("Y U always run once?");
}

or even worse (infinite loop):

boolean stop = false;
while(!stop);
{
  //...
  stop = true;
}

It took me hours to discover what the issue was

Good IDE should immediately warn you about such statement as it's probably never correct (like if(x = 7) in some languages).

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
5

; terminates the statement.

if(name != null && value != null);

is equivalent to:

if(name != null && value != null)
{
}

And the following code is simply a block of code.

P.P
  • 117,907
  • 20
  • 175
  • 238
2
if(name != null && value != null);
{
    System.out.println("Values not null");
}

is equivalent to:

if(name != null && value != null){}

{
    System.out.println("Values not null");
}
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
2
if(name != null && value != null);

Here your if statement got finished due to semi-colon...

So, it is just like an empty if block: -

if(name != null && value != null) {}

So your next code becomes an Initializer block: -

{
    System.out.println("Values not null");
}

Since it is an initializer block.. It will be executed always no matter what your if condition evaluated to..

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
1

It's the standard grammar rules. Semicolons terminate statements, but statements may be empty, so these lines:

if (...);
{
}

are equivalent to:

if (...) /* do nothing */ ;

{
    ...
}

The following { ... } statement just looks like any other code block, and will always be executed, because the if statement is done with by then.

Alnitak
  • 334,560
  • 70
  • 407
  • 495
1

Your code is equivalent to:

if(name != null && value != null) {
   // empty code block
}

System.out.println("Values not null");
Eugene Retunsky
  • 13,009
  • 4
  • 52
  • 55
1

The semi-colon ends the statement, and thus detaches the if from the following block.

Note that blocks can be arbitrary.

{
System.out.println("This is some code");
}

if(true); This is valid, and it does nothing. The language allowing this is pretty stupid, although IDEs should catch these issue with warnings and the like.

Stefan Kendall
  • 66,414
  • 68
  • 253
  • 406
0

One bare ; is a whole empty statement. After the if there has to be exactly one statement that will be executed when if is true. The one statement that is executed in your case is the empty statement. You can combine more statements to one with {statement; statement;...}

halex
  • 16,253
  • 5
  • 58
  • 67
0

Understand that conditional statements needn't always follow with opening and closing braces. Most languages will allow you to simply emit the braces if you only want to execute a single statement when the terms of the condition are met.

Meaning that the following is completely valid, for instance:

if (var1 == true && var2 == true) var3 = 'both true';
{
    //block here, this is always executed regardless of the statements outcome
}

Essentially, your code does exactly this. Except your single statement is determined to be ; (yes, this is considered a statement).

What you wrote is the same as:

if(name != null && value != null) {
    // do nothing
}

System.out.println("Values not null");
anditpainsme
  • 601
  • 1
  • 7
  • 14