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?
I can't think of an occasion where it is useful. It can be useful for loops like
or
If you use your code formatting in your IDE regularly these sort of bugs become obvious. Some IDEs highlight this as a probable bug as well.
I'd agree with you there's no useful purpose to this for a human. I suspect it's there because it simplifies the language definition; it means that the thing that comes after an
if
is e same as the thing that comes after awhile
, for instance.If you use an
if
statement, the first statement after theif
will be executed if the condition is true. If you have a block after theif
(with curly braces), it counts for that whole block. If there is no block it counts for only one statement. A single semicolon is an empty statement. You could also write the code from you example like this:Why does it happen?
Java Language Specification says that:
It essentially means that you want to execute empty statement if a==b
What should you do:
There are two main solutions to this problem:
You can avoid problems with empty statement by using code formatter and surrounding stuff inside
if
with{
and}
. By doing this Your empty statement will be much more readable.You can also check tools used for static code analysis such as:
They can instantly highlight problems such as this one.
I would recommend to combine both solutions.
Why? It's because its easier for compiler writers. You don't have to make a special case to check for semicolons after
if(cond)
and has an added usage of allowingEven though it's actually a terrible idea to allow this. It's just easier to allow and then to add a case to check this.
A few definitions from the jls explain this (chapter 14):
Blocks are Statements
As stated here, a
Block
is aStatementWithoutTrailingSubstatement
, which in turn is aStatementNoShortIf
, which is aStatement
. Thus where ever any of these is required, we can insert aBlock
.The if-clause
Though this is as well the case for
for
andwhile
-loops, I'll useif
-statements. These rules are pretty much the same. The syntactical description ofif-statements
can be found here.So we can use our block here.
But why does it work with ; ?
;
is defined as theEmptyStatement
(link), which is as well aStatementNoShortIf
. So in conditional pieces of code, likeif-statement
and loops, we can replace aBlock
with aEmptyStatement
, if aStatementNoShortIf
orStatement
is required.Thus
if(Expression)EmptyStatement
works.Why doesn't this give an error?
Pretty simple: java gives an error if it finds invalid syntax. But
if(Expression)EmptyStatement
is perfectly valid syntax. Insteadjavac
gives a warning if launched with the proper parameters. The full list of warnings that can be dis-/enabled lists the warning-nameempty
for this purpose. So compilation with-Xlint:all
or-Xlint:empty
will generate a warning about this.Your IDE should have an option to enable this kind of warning as well. For eclipse, see @nullptr's answer. In IntelliJ, you can press
Ctrl + Shift + A
, enterempty body
into the search field and enable the warning (marked in the image)What is this even used for?
To be honest, there's not much use in it from a minimalistic point of view. There's usually a way to get things done without a "do nothing" command. It's rather a question of personal preferences, whether you rather use
or
and same would apply to other cases, in which the
EmptyStatement
is used. An important point to consider on this topic is readability of code. There are occasions, where code becomes more readable by using the no-op. On the other hand there are cases, where code becomes quite a lot harder to comprehend with using theEmptyStatement
- the above example would count to the later IMO.