Why there is no compile time error? Strange - Java - java

I had an if statement checking some value, And encountered a weird bug(Not sure!). My code was incorrect syntactically and in result it produced a wrong result, however eclipse didn't raised any error while compiling. Why My below code worked?
if((this.trackPointList.get(point).getTurnOutId().equals(seg.getSegRef().getTurnOut())) && seg.getSegRef().getKind().equals("arc")); // <---- See here I have semicolon
{
... code to run ...
}
Above code check only first condition and ignores seg.getSegRef().getKind().equals("arc") but I guess this should raised an issue at compile time, Am I right? My logic worked once I debugged it by skimming line by line and found this semicolon. I will appreciate if someone could explain, if it is a valid syntax.
Enlighten Me, Please!

The ; makes Java think that the body of the if conditional is complete, even if there is no other code preceding it. In effect, the code in the if statement is executed, but no body exists because the ; is there.
The { ...code to run...} is just a code block that executes, and anything declared inside that block is not visible outside the block. It will always run here because it's not part of the if block.
edit: here's another stack overflow question about the { } blocks: What do curly braces in Java mean by themselves?

The code is syntactically correct. You can write ifs without braces, like:
if(condition) statement;
Having empty statements is also valid. For instance this code is valid:
int a = 0;;
;;;
So an empty if is valid as well, although it doesn't make much sense :)
if(condition);

An if statement followed by a semicolon is called an "empty if statement".
It rarely is of any use, but it's syntactically legal.
You can write something like this
if ( doSomethingThatReturnsABoolean() )
; // Empty statement
else
doSomeOtherThing()
but it would be better to write
if ( !doSomethingThatReturnsABoolean() )
doSomeOtherThing()
Regarding your observation that only the first condition gets checked:
If the first condition returns false the second condition will not get checked, because
(false && secondCondition)
always equals to false, so the value of secondCondition is irrelevant.

The ; after the if(..) statement represents an empty statement that is executed conditionally when the if(..) evaluates to true. The { .. } represents a code block that always executes with it's own scope.
The second condition may be ignored if the first condition is false due to short-circuit evaluation.

if(condition); is equivalent to if(condition){}
same thing with for loop & while loop:
for(;condition;); is equivalent to for(;condition;){}
while(condition); is equivalent to while(condition){}

Related

Empty if-statements [duplicate]

This question already has answers here:
Semicolon at end of 'if' statement
(18 answers)
Closed 9 years ago.
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.)
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):
Window → Preferences → Java → Compiler → Error/Warnings
EDIT
As #nullptr pointed out in his answer, there exist an IDE warning for this, you need to set warning on Empty statement.
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.
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:
Thanks to Maroun Maroun for putting me on the right track.
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.

Trouble with .equals() and ==

I'm having trouble with these if statements and can't figure out the problem:
If I try changing them to a nested if, else if format I get a compiler error saying "else" with no if statement.
The if statements don't even work, as you can see from the ouput below they all run even when the strings aren't equal.
Any help would be great. Thanks!
if (labelArray[0] == e.getSource() && myAppliance.size() >= 1) {
if (myAppliance.get(0).getClass().getName().toUpperCase().equals("CLOCK")); {
System.out.println(options[0]);
System.out.println(myAppliance.get(0).getClass().getName());
infoBox((myAppliance.get(0).toString()),"Info");
}
if (myAppliance.get(0).getClass().getName().toUpperCase().equals("LAMP")); //"Clock", "Lamp", "Television"
{
System.out.println(options[1]);
System.out.println(myAppliance.get(0).getClass().getName());
infoBox((myAppliance.get(0).toString()),"Info");
}
if (myAppliance.get(0).getClass().getName().toUpperCase().equals("TELEVISION")); {
System.out.println(options[2]);
System.out.println(myAppliance.get(0).getClass().getName());
infoBox((myAppliance.get(0).toString()),"Info");
}
}
Output:
Clock
Clock
Lamp
Clock
Television
Clock
Remove the ; at the end of the lines with the ifs.
remove the ; from immediate after if statements, compilers take them as statements and it defeats the purpose of using if itself.
Ifs work on the next statement they can take, so they'll run on the next line or treat a block enclosed on curly braces as a statement. By writing ; after the if, it's basically using an empty statement, then just proceeding to execute your block of code regardless.
Just remove the ; and it should work.

Why I am not getting any Warning or Error when writing ';'?

I have written these three lines below inside my Java code:
ArrayList<String> QuestionID = new ArrayList<String>();
;
ArrayList<String> QuestionType = new ArrayList<String>();
It compiles and runs perfect without any problems.
Why does it do so?
I cannot understand why I am not getting any warning or error in second line.
Somebody decided that an empty statement is valid. That's all there is to it. Allowing empty statements is sometimes useful, for instance for for loops with empty bodies.
As an example, here's how to find the root node of a tree (assuming there's a parent linkage, and that the root node has no parent):
for (Node parent = anyChildNode; parent.getParent() != null; parent = parent.getParent())
; // this for loop has no body, so an empty statement takes its place
Because you are writing an empty statement, which is perfectly valid.
Here you will find some more explanation.
From the above link -
The usefulness of this type of statement is limited. The main use that
I can think of is to fulfill the statement required for a loop
structure.
Here is an example that I recently used:
while ( sf(++n) != i) ;
This loop will constantly call the method sf with increasing values of
n until the return value of sf(n) is equal to i. Each loop in Java
must have some code to execute in the loop body. In this case, all
necessary work is done in the condition, and so the mandatory loop
body is an empty statement.
While there may be other (more clear) ways of writing this bit of
code, this is an example of where that empty statement can be used.
Not only is it allowed, but it has its own section in the JLS. As expected:
An empty statement does nothing.
Even more:
Execution of an empty statement always completes normally.
Which means that the following code:
;
will never throw an exception. Good to know ;-)
";" is considered as a line code without any instructions.
There's no syntax error.
#if DEBUG
#define ASSERT(_x) Assert(x)
#else
#define ASSERT(_x)
#endif
ASSERT(test); // Results in null statement in non-debug builds
Empty semicolon means there is "empty statement" before that. Thats perfectly valid case.
; means "execute nothing";
Good article about usage of empty statement
Its a valid statment and similar to instructing compiler to do nothing.
Empty statement came to Java from C where you could find it very useful for things like
strcpy(char *s, char *t) {
while(*s++ = *t++);
}
Empty Semi Colon is a valid token in JAVA and it denotes an empty statement.

Java - Very basic syntax

Basically I'm quite new to Java and just been given some code which reads:
if (n > 1)
l--;
m = l;
Although I'm wondering whether this would be equivalent to either one of these, and if so which and why?
#1
if (n > 1) {
l--;
m = l;
}
OR
#2
if (n > 1) {
l--;
}
m = l;
It's equivalent to the second one. The if statement executes the next statement if its expression evaluates to true. It doesn't matter to the compiler if the next statement is a single statement (as it is in your original code sample) or a block (as it is in your second revision).
It's the same as the second block of code.
When you don't see braces following a "grouping" statement (the if statement, in your example), it means that only the next line falls within the scope of that grouping statement.
Going beyond what the question asks, languages such as Java, C/C++, and C# use braces to declare blocks of code, whereas languages such as Python use whitespace. You can think of line of code is a block by itself. Blocks can be incrementally built by combining more blocks. This is done by grouping blocks; in Java, this is done through curly braces. When the if statement is evaluated (or a for loop, or a while loop, etc), the next outermost block falls under that statement.
the 2nd option.
If there's no { }, only the following statement is part of the If case
Obviously #2, because a if statement only takes the first expression after it into account. That is why it is always important to use brackets around your statements, both for clarity and fewer bugs. There is nothing more frustrating than spending hours wondering why code doesn't work because you forgot to add a bracket somewhere

While Loop Weirdness in Java

I noticed that java (hence probably C) has no problem with this:
while(condition1) {
//do somethin'
} while(condition2);
Is this the same as:
while(condition1 && condition2) {
//do somethin'
}
No, you have two loops.
while(condition1) {
// do something
}
while(condition2); // second loop which does nothing.
The second loop is the same as
while(condition2) { }
EDIT: My suggestion is to use the automatic formatter in your IDE regularly. Otherwise you can create formatting which suggests the code does things it doesn't.
example 1
if (condition)
statement1;
statement2;
statement3;
In this example, it appears that the first two statements are part of the if condition, but only the first is.
example 2
http://www.google.com/
statement;
Doesn't look like legal Java, but it is, not for the reasons the formatting suggests ;)
No, they are different.
The first while(condition1) will run first.
Then comes while(condition2), which has nothing after it except a single ; which means it's just some empty statement.
Remember that in control blocks like if, for, while, if you don't use the {} braces, then only the first immediate statement after it will be considered part of it.
Example:
if (condition)
System.out.println("hello"); // prints only if condition is true.
System.out.println("no"); // not bound to the 'if'. Prints regardless.
while (condition)
; // do nothing!
System.out.println("something"); // not bound to the while
Edit The empty while loop is mentioned in the Java code conventions
7.6 while Statements
A while statement should have the following form:
while (condition) {
statements;
}
An empty while statement should have the following form:
while (condition);
There is no construct is java as shown in the first form. You have probably seen
do {
} while (cond)
EDIT : You are misreading the first form. There should have been a line break after the }. This confused me as well.

Categories