(Not So) Stupid Questions 14: Why Do Pointless if Statements Even Compile?
10/24/2006
Editor's note: Sometimes the most interesting discussions begin when someone says, "This may be a stupid question, but ...." If the person asking the question has taken the time to think about the problem before asking, the question is often not stupid at all. The uncertainty points out an ambiguity in the specs, holes in the docs, or a search for how more experienced programmers might address a particular problem. From time to time, we will print one of the "(Not So) Stupid Questions" we receive and invite our readers to answer the question in the feedback section.
Remember that new people are joining the Java community all the time and may be looking for help from those with more experience. Also, those who began with Java as their first language can benefit from those coming to the community with experience in other languages. As always, answer the questions with kindness. You are also welcome to submit your questions to
This may be a stupid question, but ... "Why is if (true); considered valid Java syntax?"
First thoughts:
Quite often I track down a bug in my code to:
if ( condition );
{
consequence;
}
When of course what I meant to type was:
if ( condition )
{
consequence;
}
That is to say, without the first semicolon. If you accidentally put in the semicolon, the consequence block gets executed regardless of the outcome of the if.
It would be great if the compiler would catch such things, but for some reason it compiles because it is considered valid syntax. So my question is, why would anybody want to do an if condition that has no consequence? It feels a bit C-like to me. Would it be too late to tweak this corner case of the language spec (maybe with a -source compiler flag) to stop this category of bugs?
I'm really looking forward to a response that tells me:
Why doesn't the compiler catch the pointlessness of if (true);?
You might want to invoke some method
2007-03-01 08:00:36 pinpinokio
[Reply | View]
You might want to invoke some method in the condition and check the result of this invokation. If the result doesn't satisfy you, you can do nothing. Probably something like :
if (!(iterator = iter.next())) ;
else ...
well i am also wondering why?
2006-11-02 11:23:07 prasanth_jvrs
[Reply | View]
Well guys,even compiler is not complaining when we put semicolon anywhere after curly braces except like do while etc...
for example it didnot complain when we put;
class IfTrueExample {;;;;
public static void main(String[] args)
{;;;
static void m1() {;;;
......... so on
well i am also wondering why?
2008-10-02 13:41:16 oyunara
[Reply | View]
well i am also wondering why?
2006-11-02 11:37:54 prasanth_jvrs
[Reply | View]
It is looking like semicolon is processed as part of compiler instructions so it depends on the statement when compiler will complain.
Like class IfTrueExample {;;;; here all semicolons will be processed and it will ignore as the empty semicolons will be ignored...but the case of return;;; it will complain from the 2nd semicolon as it cannot process the instructions after 1st semicolon.So it really depends on the instruction given to compiler
why not raise a bug?
2006-10-28 02:05:16 asjf
[Reply | View]
to me, this is clearly the kind of check the compiler should make as the odds are that 100% of the time this appears in code, someone has made a typo that will likely lead to a bug. If you feel strongly, then why not raise a bug against the language spec? it might break some existing code, but it should break that code imho
Empty statements in the for loop are common and differ as they can be used legitimately
Tools that generate code can easily introduce a dummy method doNothing() or dummy statement to work around this
why not raise a bug?
2007-03-16 11:55:18 dividezero
[Reply | View]
I would instead suggest that instead of raising a compiler error, make it a warning, the same the compiler creates warnings for:
int foo = 6;
foo = foo;
the ;;;;;;;;'s in question are probably being caught as "lines of code" but since they do nothing, they are eaten by the compiler and make no change in the bytecode.
Use Lint4j or other static analysis tools
2006-10-25 21:36:03 sreich
[Reply | View]
I added an audit for exactly this case to Lint4j, which audits Java source code for obvious and not so obvious coding problems.
When you use the Eclipse plugin with the builder support, the warning will pop up the moment the file is saved.
Compiler is meant for only Syntax Checking
2006-10-25 11:22:54 sunnyjava
[Reply | View]
Resposibility of compiler is just to compile the code from one form to another without looking into the correctness,performance etc issues.
But it would be helpfull to have command line options(possibly in -X list) to scan such things.
the same question applies for string comparision(== or equals),overiding equals() without overiding hashcode(),etc.
Again code review tools are there to catch such mishaps, so still we can keep compiler out of this issues.
Because empty statement are allowed
2006-10-24 11:19:07 farnulfo
[Reply | View]
Empty statement are allowed in java grammar like :
java code :
;;
I remembered that in ADA language empty statement are not allowed, if you don't want to do anything you must say it by using null keyword:
ADA code :
;; => compiler error
you must use : ; null ;
ADA is one of the most compiler checking language I have seen : when you use a switch statement with a integer and you only have case 1, .. case 3 , you've got a compiling error that interval [-999999999,0] and [4,9999999] are not defined !
ANd this is an error not a simple warning : You must use a default statement.
So, why are they allowed in Java then?
2006-10-24 12:02:42 nielsull
[Reply | View]
As several people have pointed out, the compiler allows it because the Java standard allows it. And, yes, there are several tools that will catch errors like these.
So, the real question is: Why does Java allow this?
It doesn't make much sense, if you think of Java purely as a language humans write code in.
But Java is also used as an intermediate language, e.g. for JSP pages. And sometimes JSP is generated automatically (e.g. using XSLT). When developing systems like this, it does make life a lot simpler if you are allowed an occasional empty statement,
so that you can write stuff like
<myframework:if cond="useTop">;<%@ include file="userWrittenTop.jsp" %>;<%/myframeworktaglib:if>
Now, if the framework user happens to want to use a blank userWrittenTop.jsp? Should he get a Java compiler error, which he cannot really do anything about?
PS: Don't point fingers at this (ab)use of JSP - my point is that Java should not disallow it.
And in real life, the code may be a lot more complex.
Well, the compile will fail in other scenarios where the code is syntactically correct but obviously wrong ... e.g., if you are catching an Exception that is never thrown, or other cases of unreachable code. I assume this might have been the original posters point.
I'm guessing the reason for allowing a no-op statement following an "if" is to allow something like:
if (some-test)
{
// do nothing ... pretty much the same as a ";"
}
else
{
code here ...
}
To the compiler, I assume the empty brackets are effectively the same as a semi-colon. I write conditionals like this if it makes the code more clear.
Chalk this up to coding conventions
2006-10-24 07:55:49 jgustie
[Reply | View]
I think this is definitely a case where following Java's coding conventions to write readable code helps. Section 7.4 of Sun's coding conventions for Java suggest that you use:
if (condition) {
statements;
}
This helps prevent the problem above, though I imagine it sparks a heated debate about where the curly bracket belongs.
When using an IDE, running the code formatter can help spot this type of bug as well. When formatted with Eclipse using the Java conventions, the example above becomes:
if (condition)
;
{
statements;
}
It is much clearer using properly formatted code that there is a problem.
Not the compiler's job
2006-10-24 07:08:44 jattardi
[Reply | View]
The compiler's job is to simply parse Java code and make sure all the statements are valid. A single semicolon is a valid statement, and all an if statement needs is one valid statement following it.
Checks like these are better left to a source code analysis tool, something like FindBugs or Checkstyle.
use for an empty statement
2006-10-24 06:56:33 schack
[Reply | View]
It might be useful (although I cannot imagine a concrete example) that you only want to use the side effects of the condition.
Like:
If ( Sammy.loves(Rosie) || Rosie.hates(me));
with both functions doing stuff before returning a boolean and Rosie.hates(me) only being executed in case Sammy.loves.(Rosie) has returned false.
Empty statements are allowed
2006-10-24 05:07:28 mnesarco
[Reply | View]
Its just like a for statement with an empty block:
for (i=0; i<100; i++);
I think the semantics of the program is not a compiler problem.
Empty statements are allowed
2006-10-24 09:43:17 afishionado
[Reply | View]
On that thread,
for (;;)
foo();
is valid syntax as well, only the no-ops are in the conditional, not the body.
Basically, anywhere you can put a statement, you can put an empty statement, and the compiler doesn't care.
Empty statements are allowed
2006-10-24 23:29:43 rbirenheide
[Reply | View]
That is not entirely the case:
return;;
will not compile. In that case the compiler does take the decision whether your empty statement makes sense or not.
Empty statements are allowed
2006-10-25 04:55:26 jwenting
[Reply | View]
But for an entirely different reason, as your empty statement is unreachable code. Anything else there would also be rejected!
An empty statement may be intentional, therefore the compiler will allow for it. Possibly an explicit nop instruction like Assembly or Ada has would have prevented some errors, but the cost is code readability.