Java - Very basic syntax - java

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

Related

Detection of Loops in Java Bytecode - Distinguishing back edge types

Background:
Before asking my question, I wish to state that I have checked the following links:
Identify loops in java byte code
goto in Java bytecode
http://blog.jamesdbloom.com/JavaCodeToByteCode_PartOne.html
I can detect the loops in the bytecode (class files) using dominator analysis algorithm-based approach of detecting back edges on the control-flow graphs (https://en.wikipedia.org/wiki/Control_flow_graph).
My problem:
After detection of loops, you can end up having two loops (defined by two distinct back edges) sharing the same loop head. This can be created by the following two cases as I have realized: (Case 1) In the source code, you have a for or while loop with a continue statement, (Case 2) In the source code, you have two loops - an outer loop that is a do-while and an inner loop; and no instructions between these loops.
My question is the following: By only looking at the bytecode, how can you distinguish between these two cases?
My thoughts:
In a do-while loop (that is without any continue statements), you don't expect a go-to statement that goes back to the loop head, in other words, creating a back edge.
For a while or for loop (that is again without any continue statements), it appears that there can be a go-to statement (I am not sure if there must be one). My compiler generates (I am using a standard 1.7 compiler) this go-to instruction outside of the loop, not as a back edge unlike what is mentioned in the given links (this go-to statement creates a control-flow to the head of the loop, but not as a jump back from the end of the loop).
So, my guess is, (repeating, in case of two back edges), if one of them is a back edge created by a go-to statement, then there is only one loop in the source code and it includes a continue statement (Case 1). Otherwise, there are two loops in the source code (Case 2).
Thank you.
When two loops are equivalent all you can do is to take the simplest one.
e.g. there is no way to tell the difference between while (true), do { } while (true) and for (;;)
If you have do { something(); } while (false) this loop might not appear in the byte code at all.
As Peter Lawrey already pointed out, there is no way to determine the source code form by looking at the bytecode. To name an example closer to your intention, the following single-loop code
do action(); while(condition1() || condition2());
produces exactly the same code as the nested loop
do do action(); while(condition1()); while(condition2());
Likewise the following loop
do {
action();
if(condition1()) continue;
break;
} while(condition2());
produces exactly the same code as
do action(); while(condition1() && condition2());
with current javac, whereas surprisingly
do {
action();
if(!condition1()) break;
} while(condition2());
does not, which only shows how much the exact form depends on compiler internals. The next version of javac might compile them differently.

How to jump in java

I have a code like this
public class Test
{
public static void main(String[] args)
{
continue s;
System.out.println("I am not supposed to print this");
s:
System.out.println("I am suppose to print this");
}
}
I get the error
java: undefined label: s
What is wrong ?
Basically, there is no practical way to do that in Java. You appear to be trying to do the equivalent of a "goto", and that is not supported in Java. The break label and continue label statements can only branch to an enclosing labelled statement.
Now according to the Java formal grammar you could write this:
s: {
continue s;
System.out.println("I am not supposed to print this");
}
System.out.println("I am suppose to print this");
but that still won't compile for two reasons:
The continue is only allowed to branch to a label on a loop statement. (A break doesn't have that restriction ... but ...)
The continue (or a break) makes the next statement unreachable.
See also: Alternative to a goto statement in Java
But there is one rather tricky way to get your code to "work":
static final boolean flag = true; // class attribute ...
...
s: {
if (flag) break s;
System.out.println("I am not supposed to print this");
}
System.out.println("I am suppose to print this");
The "test" there will be evaluated by the compiler so that the break is effectively unconditional. But the JLS says that the first println will be treated as reachable, so that you won't get an unreachable code error.
I guess this might be useful if you are generating this source code. Apart from that, it is (IMO) just a curiosity. It is simpler to do this with a regular if / else statement ... or by deleting the first "print" entirely.
Jumping like this is not possible in Java, only way to jump is from loops, while and do.
What is the "continue" keyword and how does it work in Java?
Read #Heinzi answer
2.2.6 No More Goto Statements
Java has no goto statement. Studies illustrated that goto is (mis)used more often than not simply "because it's there". Eliminating goto led to a simplification of the language--there are no rules about the effects of a goto into the middle of a for statement, for example. Studies on approximately 100,000 lines of C code determined that roughly 90 percent of the goto statements were used purely to obtain the effect of breaking out of nested loops. As mentioned above, multi-level break and continue remove most of the need for goto statements.
The Java Language Environment, James Gosling
and Henry McGilton, 1996
There is no "goto" in java. And "continue" does a little bit other function. You can use "continue" for example in loops like:
class ContinueDemo {
public static void main(String[] args) {
String searchMe = "peter piper picked a " + "peck of pickled peppers";
int max = searchMe.length();
int numPs = 0;
for (int i = 0; i < max; i++) {
// interested only in p's
if (searchMe.charAt(i) != 'p')
continue;
// process p's
numPs++;
}
System.out.println("Found " + numPs + " p's in the string.");
}
}
In the example above, if for example searchMe.charAt(5) != 'p' then the loop will continue from the beginning of loop from i=6, and numPs++; will not be processed.
You can read more about this here:
Branching Statements
continue is a keyword in Java used to skip iterations of a loop.
If you are trying to find an equivalent to GOTO, you should reconsidering how you are trying to solve your problem, GOTO is never a valid option, ever.
As far as I know, there is no goto in Java (there is a keyword, but it has no meaning)
Theoretically, Java have Jump statements return and break.
The return statement jumps out of a method, with or without returning values to the calling statement.
The break statement jumps out of loops.
As mentioned in the earlier answers, goto is not available in Java, and is not considered to be a good programming practice in procedural or object oriented programming. It existed back in the days of sequential programming.

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.

Why does the increment/decrement in a for loop not end with a statement?

Everywhere else I write a statement in Java I need to end it with a semi-colon. However, that doesn't apply to the i++ of a for loop.
How comes?
Because it's special syntax with clear and agreed-upon semantic meaning interpretable by the compiler, because the designers of C/C++/Java/etc. arbitarily decided it should be so.
EDIT:
Some commenters have pointed out that the decision isn't really arbitary, since designers did it to maintain consistency with expression vs. statement syntax. I'm glad they pointed that out, because I didn't know that was the case. In my defense, they very clearly could have made the syntax require a semicolon in that position; the decision not to, while not entirely arbitrarily, represented a choice which could have been different. Ahem.
Because the ')' rather well terminates the update statement so it would be redundant?
Both in C and C++ it's like that, and Java copied much of the syntax of those languages, for making things easier for programmers coming from them.
Also, it really isn't necessary to end the statement with a ";", since the right parenthesis ")" demarcates where the statement ends.
I would spend some time learning the differences between an expression and a statement; as described here.
The parts of a for loop are expressions, not statements. Expressions are not terminated by semicolons. i++ is an expression. Likewise, you don't put a semicolon after the i++ here:
System.out.println(i++;);
// ^ wrong
That wouldn't make any sense. The same logic applies to if, and while loops.
If you think about it, really two of the three terms in a for loop aren't really statements. Take the canonical for loop
for(int ix = 0; ix < MAX; ix++){ /* do something */ }
that's really shorthand for
int ix = 0;
while(ix < MAX){ /* do something */ ; ix++; }
Notice that there's no semicolon for ix < MAX either. In the for loop, the semicolons are simply there to separate the terms somehow -- only by co-incidence (and a lack of extra symbols) is it the same as a statement terminator.

Why there is no compile time error? Strange - 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){}

Categories