Question

By "empty if-statement", I mean something like this (note the semicolon):

if (condition);

I'm having trouble thinking of an application for this. With a while loop you can do this:

while (callUntilReturnsFalse());

But there's no such application for an if-statement. What's more, the Java compiler doesn't issue an error or a warning when confronted with such a statement. This can lead to large and silent problems, especially with a long and convoluted statement:

if ((functionA() && functionB(getFoo()) ||
    checkForComplexCondition(arg1, arg2, getBar(getFoo())));
{
    doStuff();
}

My question is: why is this allowed in Java? And, more importantly, can I enable an option to cause a warning when this happens?

(This question was asked before with regards to C#, which does issue a warning, but I was hoping to find a way to cause a warning with Java.)

Was it helpful?

Solution 2

why is this allowed in Java?

See Java Language Specification (14.6. The Empty Statement):

An empty statement does nothing.

It's simply allowed and it's equivalent to (and will be translated to):

if (condition) {  }

Which means, if the condition is true, do nothing.

If you're using eclipse, you can look here, you might find something useful (I'm not sure there exists such an option for semicolon terminator):

WindowPreferencesJavaCompilerError/Warnings

enter image description here


EDIT

As @nullptr pointed out in his answer, there exist an IDE warning for this, you need to set warning on Empty statement.

OTHER TIPS

There's one construct that I use fairly frequently which the "null statement" makes clearer and easier to understand. Here's an example:

for (int i=0;  i < argc;  i++)
{
   if (argv[i]=="left")
      hpos++;
   else if (argv[i]=="right")
      hpos--;
   else if (argv[i]=="up")
      ;
   else if (arv[i]=="down")
      ;
   else fprintf(stderr, "Unknown option \"%s\\n".", argv[i]);
}

In this case, I still want to check for the existence of certain options, while only executing code for some of them. In this case, using the null statement, as above, makes the function and structure of the code more readable and comprehensible to the next guy who has to come along and maintain it.

There are certainly ways to restructure this code to not require the null statement. But I don't believe that its intention will be as clear as in the code snippet.

I found a warning for this in Eclipse as Empty statement:

example

Thanks to Maroun Maroun for putting me on the right track.

I don't think this is truly relevant to the intent of the question but I think it should be stated as it is relevant to the essence of the question.

There is an effect of an:

if(variable);

if the variable is volatile. It''s effect is to cause a memory barrier to be honoured between the current thread and any other threads accessing the variable.

public volatile variable;
....
if(variable);

See here for a more detailed discussion.

I cannot imagine any real value to putting this kind of statement in your code but I felt it important to note that there is a real effect to this statement in this very specific situation.

I don't see so much danger in the possibility of an if with an empty statement. The rationale behind it resides in the grammar of the Java language, which allows the empty statement ;:

Block: 
    { BlockStatements }

BlockStatements: 
    { BlockStatement }

BlockStatement:
    LocalVariableDeclarationStatement
    ClassOrInterfaceDeclaration
    [Identifier :] Statement

LocalVariableDeclarationStatement:
    { VariableModifier }  Type VariableDeclarators ;

Statement:
    Block
    ;
    Identifier : Statement
    StatementExpression ;
    if ParExpression Statement [else Statement] 
    assert Expression [: Expression] ;
    switch ParExpression { SwitchBlockStatementGroups } 
    while ParExpression Statement
    do Statement while ParExpression ;
    for ( ForControl ) Statement
    break [Identifier] ;
    continue [Identifier] ;
    return [Expression] ;
    throw Expression ;
    synchronized ParExpression Block
    try Block (Catches | [Catches] Finally)
    try ResourceSpecification Block [Catches] [Finally]

Mind that this is true for almost all imperative languages.

I mean it can be dangerous and difficult to find as every other empty body in case you forgot any implementation, certainly nothing I would lose the sleep for. In a long and convoluted statement you could get problems because of a ( ) closing the wrong pair of expressions or even for thinking your condition wrong (especially with many && and ||).

I'm mostly a C# developer, although I have a little Java background. But I think my answer applies to both. I suspect it's not an intentional feature, but more of an emergent feature. The grammar of the language goes (roughly)

if (*condition*)
    *statement*

Unfortunately the below are both valid statements (I checked, you can drop as many into C# as you like and the compiler doesn't complain):

;

{
}

Therefore the construct that you highlighted is allowed.

The condition could be a function call with side effects. It wouldn't be correct to treat it as an error or warning.

In the statement

if  (eval) { //pseudo-code
}

Sometimes data is actually changed in evaluation of (eval). For example, in

while (someIterator.next()) {
}

Calling next() actually changes the state of the someIterator object.

And of course there is the classic example that usually happens from a typo (and is not recommended)

int x;  
if (x = getNumberOfWidgets() > 5) {
}

Conventional wisdom advises against coding this way, as it is harder to tell what is going on. However, the statements are legal and so that is one reason why such an 'if' statement is allowed.

I believe that they left it in because it can increase code readability. Even if nothing should be done for a case you may still want to let people know that the case is important.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top