IntelliJ complaining "for statement does not loop"? - java

This is the code I have:
public enum Modification {
NONE, SET, REMOVE;
}
boolean foo(){
for (S s : sList) {
final Modification modification = s.getModification();
switch (modification) {
case SET:
case REMOVE:
return true;
/*
case NONE:
break;
*/
}
}
return false;
}
And when the code is as seen above, IntelliJ will say:
'for' statement does not loop less... () Reports any instance of for,
while and do statements whose bodies are guaranteed to execute at most
once. Normally, this is an indication of a bug.
Only if I make the following change, IntelliJ will be happy:
for (S s : sList) {
final Modification modification = s.getModification();
switch (modification) {
case SET:
case REMOVE:
return true;
case NONE:
break;
}
}
Why is my for loop not looping if case NONE: is not included in the switch statement?

I just tried this in eclipse and you end up with a compiler warning on the switch statement.
The enum constant NONE needs a corresponding case label in this enum switch on Modification
To resolve the warning I'm given the following options.
Add default case
Add missing case statements
Add #SuppressWarnings 'incomplete-switch' to foo()
If I add the missing case statement then the warning no longer appears. The same as adding the missing case makes your error warning disappear from intellij.
Without the statement for case NONE you can only see two cases, both of which return true. Without knowing the structure of Modification and the extra value of NONE it looks like this loop would just return true on the first iteration of the loop.
Of course the compiler should actually know that there are more values for Modification than SET and REMOVE so the warning is just for good style. Basically your code works but here's how to improve it.
I would choose to add a default statement rather than the missing case. This would be more future proof in case more values are later added to the enum. E.G.
switch (modification)
{
case SET:
case REMOVE:
return true;
default:
break;
}
Personally I'm not a fan of using the fall through on switch statements. What you gain in making the code concise you lose in legibility IMHO. If someone later comes and adds a case between SET and REMOVE it could introduce a bug. Also, having a return statement mid-way through a method can also cause problems. If someone wants to add some code just before the return they may miss all the places. If the method is very simple then multiple returns is fine but you've stated that this is a simplified example and so if this block of code is complicated I would avoid it.
If you're able to use Java 8 then this looks to be the perfect use case for the new stream API. Something like the following should work.
return sList.stream().anyMatch(
modification -> (modification==Modification.SET || modification==Modification.REMOVE)
);

i assume these are your only three cases right?, so basically its saying you are going to hit one of the first two and instantly return true, therefore not looping, just add a default case and everything should work ok, this is good practice also btw.
basically it cant see a case where it doesnt just return instantly without iterating the loop

I'd say its a false positive.
1st indication:
If you run your code through a debugger - and have elements with NONE modification in the list before an element with other modifications - it will actually loop.
2nd indication:
When you look at the generated bytecode, it transforms the switch statement to (sort of - its not exactly the same)
for (S s : sList) {
Modification modification = s.getModification();
switch (modification.ordinal()) {
case 1:
case 2:
return true;
}
}
If you put that in your code, IntelliJ does not complain.
3rd indication:
the warning dissappears if you put an additional statement before the return, i.e. System.out.println();
switch (modification) {
case SET:
case REMOVE:
System.out.println()
return true;
Seems you tricked the inspection with the missing case label and could simply ignore the warning.

I think that IntelliJ's inspections is wrong. I reported it to JetBrains
Edit : it's fixed

Your switch case always breaks or returns. In the first case, you do nothing aka it falls through. The second case returns which causes both the switch and the loop to stop. In the third case you break the switch statement which causes it to stop. It does not however stop the for loop (aka, it keeps iterating).
Either add specific functionality for the SET case or change your behaviour on the REMOVE and NONE cases.
public enum Modification {
NONE, SET, REMOVE;
}
boolean foo(){
for (S s : sList) {
final Modification modification = s.getModification();
switch (modification) {
case SET:
// This case falls through to the REMOVE case
case REMOVE:
return true; // This statement stops the switch, loop and returns true
case NONE:
break; // This statement stops the switch and continues the loop.
}
}
return false;
}
Your switch is not looping without the NONE case because return breaks the loop and returns a value from the function. break breaks the switch loop but continues the for loop.
By request of OP an extra explanation.
Falling through means the next case will be executed until a stop (break or return) is reached. This makes the following code snippets equivelant:
case SET:
case REMOVE:
return true;
is the same as:
case SET:
return true;
case REMOVE:
return true;

Related

Philosophy of variable's scope in a switch statement

As answered in this question here, the scope of a variable inside of a case belongs to the entire switch statement itself, not just the case. Therefore, this does not compile (duplicate local variable):
int key = 2;
switch (key) {
case 1:
String str = "1";
return str;
case 2:
String str = "2";
return str;
}
I'm interested in mainly two things...
What's the philosophy, or design principle, behind this behavior? (Maybe I'm even asking for the motivation for the switch statement as a whole?)
How does this happen? How does this code look at the bytecode, or even assembly, level?
For better or worse, the semantics of switch in Java were heavily influenced by the semantics of switch in C. And, while we as programmers tend to think of a case label followed by some statements and a break/continue/return as a logical unit, that's not actually how it works, and no such construct exists at the language level. In a switch, break and continue are just statements, and when you execute a switch, you start at the matching case label and execute the remainder of the block. It just so happens that most of the time, you'll hit a break or continue or return before that happens. (See JLS 14.11.) The key sentence is:
All statements after the matching case label in the switch block, if any, are executed in sequence.
Many people believe (IMO, reasonably so) that the switch statement in Java has its priorities backwards; the language treats fallthrough and other control flow oddities as if they were normal case, and break as the exceptional case. But of course, in real code, it's the other way around. (How did Java acquire these backward priorities? By copying from C.)
The scoping rule for switch statements flows pretty directly from this view of the world; if the body of a switch is an undifferentiated block that happens to be peppered with case labels, of course its one big scope. Never mind that this is not actually what almost all developers want almost all the time.
In addition to confusing scoping and fallthrough-by-default, Among the other things people regret about switch in Java is that it is only a statement, not an expression. See JEP 325, which addresses all of these problems (in a backward-compatible way), which will likely be a preview features in Java 12.
Just put a pair of braces around each case clause:
int key = 2;
switch (key) {
case 1: {
String str = "1";
return str;
} case 2: {
String str = "2";
return str;
}
}
This will compile.

Do "nothing" while "condition"

While browsing the code for the Java 8 version of ForkJoinPool(which has a few interesting changes from Java 7) I ran across this construct (here):
do {} while (!blocker.isReleasable() &&
!blocker.block());
I'm struggling with why you would write it like this instead of just
while (!blocker.isReleasable() &&
!blocker.block());
Is it just a semantics/readability choice, since you could read the first construct as do "nothing" while "conditions"? Or is there some additional benefit I'm missing?
If you read the comments at top of the file, just below the class declaration, there is a section which explains the use of this construct:
Style notes
===========
[...]
There are several occurrences of the unusual "do {} while
(!cas...)" which is the simplest way to force an update of a
CAS'ed variable. There are also other coding oddities (including
several unnecessary-looking hoisted null checks) that help
some methods perform reasonably even when interpreted (not
compiled).
ForkJoinPool makes extensive use of compareAndSwap... from sun.misc.Unsafe and most of the occurrences of do {} while (...) in ForkJoinPool can — as mentioned by other answers — be explained by this comment under the heading Style notes:
* There are several occurrences of the unusual "do {} while
* (!cas...)" which is the simplest way to force an update of a
* CAS'ed variable.
The choice to use write a while-loop with an empty body as do {} while (condition) seems however to be a mostly stylistic choice. This is perhaps clearer in HashMap, which happened to be updated in Java 8.
In the Java 7 HashMap you can find this:
while (index < t.length && (next = t[index++]) == null)
;
While much of the code around it has also changed, it is clear that the replacement in Java 8 is this:
do {} while (index < t.length && (next = t[index++]) == null);
The first version has the weakness that if the lone semicolon happened to be deleted it would change the meaning of the program depending on the following line.
As seen below, bytecode generated by while (...) {} and do {} while (...); is slightly different, but not in any way that should affect anything when run.
Java code:
class WhileTest {
boolean condition;
void waitWhile() {
while(!condition);
}
void waitDoWhile() {
do {} while(!condition);
}
}
Generated code:
class WhileTest {
boolean condition;
WhileTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
void waitWhile();
Code:
0: aload_0
1: getfield #2 // Field condition:Z
4: ifne 10
7: goto 0
10: return
void waitDoWhile();
Code:
0: aload_0
1: getfield #2 // Field condition:Z
4: ifeq 0
7: return
}
Leaving aside any potential performance benefits, there is a clear readability benefit.
With while (X) ; the trailing semicolon is not always obvious at first glance, you may be confused into thinking that the following statement or statements are inside the loop. For example:
while (x==process(y));
if (z=x) {
// do stuff.
}
It would be very easy to misread the above as having the if statement inside the loop, and even if you did read it correctly it would be easy to think that it was a programming mistake and the if should be inside the loop.
With do {} while(X); though it is immediately at a glance clear that there is no body to the loop.
If you will read comment above the code, It is mentioned that...
If the caller is not a ForkJoinTask, this method is behaviorally equivalent to
while (!blocker.isReleasable())
if (blocker.block())
return;
}
So it is just another form to implement above code in else part...!!
In Style notes it is mentioned that,
There are several occurrences of the unusual "do {} while
(!cas...)" which is the simplest way to force an update of a
CAS'ed variable.
And if you will see implementation of ManagedLocker#isReleasable, It is updating the lock and returns true if blocking is unnecessary.
Interpretation :
Blank while loops are used to provide an interrupt until some condition reset to true/false.
Here, do { } while(!...) is a blocker/interrupt until blocker.block() will be true when blocker.isReleasable() is false. Loop will continue execution while blocker is not releasable (!blocker.isReleasable()) and blocker is not blocked !! Execution will be out of loop as soon as blocker.block() will set to true.
Note that, do{ } while(...) does not update CAS variable, but it guarantee that program will wait until variable gets updated (force to wait until variable gets updated).
You can easily make something like this with:
if(true){
//Do nothing ...
}

Switch Case statement enum not working?

I have a problem concerning switch/case statements in java in combination with enums.
In my code I want to do something based on the Enum of the type "MatchingMethods" set in the object "currentMethod".
The enum "MatchingMethods" contains several enums in the form
{EXACT_STRING_MATCHING, DEPTH_MATCHING, [...]}
Now the strange thing is though the object "currentMethod" contains an enum of the type "EXACT_STRING_MATCHING" not only the first case is executed but also the second one.
I know there is no break statement after the code of the first case but the code of the second case shouldn't be executed in my opinion because the enum "EXACT_STRING_MATCHING" doesn'T match with "DEPTH_MATCHING".
If I put in a break statement after the first case it seem to be totally fine…
My code is the following:
[...]
MatchingMethods mM = currentMethod.getMatchMethod();
switch (currentMethod.getMatchMethod()) {
case EXACT_STRING_MATCHING:
//do something here
case DEPTH_MATCHING:
comparedNodePair.setDepthMatchResult(currentMetricResult);
break;
[...]
I am totally confused…
May someone be able to help me?
You already mentioned it, you have no break - switch works like goto where the case are labels to be jumped at and no "boundaries" or functions.
This is also the biggest critique concerning switch, because no one would use goto today, but switch which is certainly similar.
But it gets executed, because once one of the case satements is true the flow of execution "falls trough" see here for some information
this is normal if there is no break statement at the end of the case block.
add the break statement is necessary if you only want the exact block to be executed.

Is the default case necessary

I have a statement that goes like this:
public $type function_name($enum e){
if(e != null)
switch(e){
case A: return x1;
case B: return x2;
case C: return x3;
//default: do some operations
}
// default or e = null
do the exact same operations
}
My question is: given that the default case is treated in the rest of the method, is it necessary (in terms of good coding style) to add it to the switch statement (basically, duplicate the code for "if anything else happens" - in this case, default for switch, e = null, etc.)?
Default case is not necessary in Switch-Case, but it is a good habit to use it and define a default case if non of the cases you have defined occur. If you're duplicating your code, it is not good!
Hope it helps.
default case is not necessary but you should always have it and log/throw exceotion. In case of some error or problem with the value passed you will know right away the problem.
If you add it to the default clause, the last line
throw new YException();
will be dead code.
Note that in no case, the code will reach the last line. If e meets the cases A,B or C, it will reach a return statement, so it will exit the function. And if none of this cases are met, the throw in the default will be reached.
In conclusion: you should add it to the default clause (it's a good practise to always include a default) and delete the last throw line.
if in combination with switch for the same variable does not make sense to me.
It can work, but it is asking for trouble.
Why not put the exception as a default action? Than you do not need duplicated code at all.

Java switch statement efficiency of default placement

Does the placing of default statement affect efficiency in Java? Is there difference between:
switch (a) {
case 0: return 0;
case 1: default: return -1;
case 2: return 2
...
case 99: return 99;
}
vs
switch (a) {
case 0: return 0;
case 1: return -1;
case 2: return 2;
...
case 99: return 99;
default: return -1;
}
Even in the most naive implementation this cannot produce a difference in performance, but with Java you are so far removed from the actual machine code this will turn into that you should definitely never even attempt to optimize this or any other similar piece of code. In fact, even if you wrote the dumbest cascade of else-ifs, you'd still stand a solid chance of JIT turning that into a superfast hash-lookup-based machine code.
No, it won't make a difference. Why? Because of this: When does the JVM know that it has to use the default body? After it checked all the other cases. So placing default: at a specific location in the which won't change performance.
I don't believe you'd see any significant performance improvements if you wrote a quick test program. At least none that would justify obscuring your code. I'd just leave the default case neatly last in the list to keep the code more readable. It's probably more important than a micro improvement in performance (if any at all)
No. The location of the switch statement makes no difference to the generated byte code other than the debugging annotations.

Categories

Resources