Today, after half an hour of searching for a bug, I discovered that it is possible to put a semicolon after an if statement instead of code, like this:
if(a == b);
// Do stuff
Which basically means that the stuff will be done whether a equals b or not, and the if statement has no point whatsoever. Why doesn't Java give me an error? Is there any situation in which this would be useful?
It is an old leftover from the days when there was more syntactic sugar to differentiate expressions from statements.
Basically, the comma was used as the list item separator, so the semicolon was used as the "list of statements" separator. The downside is in the handling of null items in lists, and null statements in blocks.
In a list of items, Java uses the explicit keyword
null
, but a "null statement" is just an empty line. Allowing the existence of an empty line is a holdover from tradition inherited from C.Why do it? Especially with an
if
statement when you know that no statements are being executed: Because some if statements have side effects:Yes, it is not the best example, but basically it says read a byte from the stream and do nothing. Might be useful in some corner cases, but even if this example isn't the best, it illustrates the intent. We want to feel the side-effects of the expression without accidentally executing any statements.
A possible use case:
Not good, but possible.
Still, I do think that the Java specification should disallow an empty
if
.If you're using Eclipse, you can make it warn you about those statements:
Java allows an empty block any place a statement block is allowed. I am sure making this a general rule for all blocks simplifies the compiler.
I agree that this is primarily the cause of bugs that are spectacularly hard to find. I always use braces around blocks, even when there is a single statement, but Java allows you to make a block with braces at any point, so using braces can not save you from this fate. For example, I once wasted 4 hours trying find something like this:
The semicolon at the end of the first line was a typo, accidentally making the statement block for the while loop empty. Because the syntax is valid the program compiled and ran fine, just not the way I wanted it to. It was really hard to find.
I can think of one situation where it is very nice that you are allowed to have empty blocks, and this is something like this:
In the above example, you want to be able to separate out various conditions. Remember, those conditions might be overlapping, so it is not always possible to rearrange the order. If one of the conditions really does not need anything done, then it is nice that Java allows you to have an empty block. Otherwise, the language would need some form of a "noop" method to use when you really do not want anything done.
I personally would prefer the explicit "noop" statement -- but that is not how Java is defined.
You can use an IF statement without
{}
if there is only a single line to be executed, so by usingif(a==b);
you are saying if they equal, execute and empty statement... So it will do nothing, and then return to your normal loop, outside of the IF block.Useful? As in "makes your code cleaner, clearer, faster, more maintainable"? Not at all. This is most likely poor, confusing code.
But it's not necessarily benign. Such a statement can perform actions and/or alter state due to methods which cause side effects, and optionally evaluate those methods due to short-circuiting of operators.
Here,
a()
orb()
may do something, andb()
will only execute ifa()
is true.As to why, I think the answer is simply that it would be worse to deviate from defined, expected behavior (e.g. statements like
while(reader.read());
) than the alternative of developers writing bad code.Writing bad code is always possible. And just to reiterate, this would be bad code in almost any case.