Is there an option in the Eclipse workspace properties to change the order that the "incomplete-switch" warning auto-populates cases within the switch statement? For example, if I have an enum:
enum TraversalType{
PREORDER,
INORDER,
POSTORDER;
}
When you use this and have the switch statement warning auto complete the cases within the body of the switch, it seems to always order alphabetically. Is there an option to change this and use the ordering, like in this example, to look like:
switch(TraversalType pType){
case PREORDER:
break;
case INORDER:
break;
case POSTORDER:
break;
}
every time, instead of just after manually entering the cases?
You can't change the ordering of case statements in the Eclipse auto complete feature of "add missing case statements". However you can sort the enum members alphabetically to match the order of the auto inserted switch cases.
Related
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;
I am attempting to create it so the user will type in a keyword and it will execute that case. This works fine, but I would like the user to also be able to write after the keyword and it will still find the correct case. For example, the user might input "SEARCH dogs and cats" and it would run the "SEARCH" case.
I attempted to do have a temporary variable that stored only the "SEARCH" portion of the string, but I received an error that it had to be a constant in the switch statements. Is there a workaround or will I have to use if else statements?
Here is some test code with the error:
switch(textField.getText)
{
case SEARCH: case textField.getText().split(" ", 2)[0]: // Error is occuring on the second case statement
// Statements
break;
case Default:
lblOutput.setText("ERROR: NOT FOUND");
}
You need to specify one of three things in a case statement:
A constant
An Enum
Default keyword
Refer to
https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11
In addition, you have a "case" within a "case" with no intermediate "switch" statement.
I am trying to explore substrings using switch case block. for now I am trying to do this:
switch(splitedString[0]){
case(.contains("int")):
}
When I need to create new object when the case is met. There is any option to activate method on the switch argument?
You can not do such thing. Also putting string in a switch statement is more like if statement.
Instead of using switch use if's
sample:
if(splitedString[0].contains("int"))
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.
For example:
3 methods exist
"map1method,
map2method,
map3mehtod"
and I want to call the right one depending on what the integer 'activemap' has currently stored in it.
I could do an If statement
"If (activemap == 1)
map1method;
elseif (activemap ==2)
..."
But is there a possible way of using the integer more efficiently?
Like a "map(activemap)method"
Also could I also call a specific array in a batch of them in the same fashion.
This is all in java by the way.
It is possible via reflection but I would urge you to stay away from that approach. Why not have all three methods built into one? One option would be to use a switch statement to handle the various cases:
void mapMethod(int activemap) {
switch (activemap) {
case 1:
// map1method
break;
case 2:
// map2method
break;
case 3:
// map3method
break;
default:
break;
}
}
Now, you can call
mapMethod(activemap)
If you want to take the reflection approach instead (which as I said I don't think you should), you can do something along the lines of
String methodName = "map" + activemap + "method";
MyClass.class.getDeclaredMethod(methodName).invoke(null);
A switch statement would be slightly easier to read:
switch(activemap) {
case 1: map1method(); break;
case 2: map2method(); break;
}
You could use reflection to build the method name up at runtime, but that wouldn't be simpler. Reflection is a lot of code.
The most effective way to do this is to either create an enum to represent the different calls and use the int as a lookup for the enum value, or if that's not possible, to use a switch statement. You can use reflection to accomplish what you're talking about (look up a method at runtime based on its name), but it's less efficient and more cumbersome than either of those options.
You can do it using Reflection, It will be something like this:
java.lang.reflect.Method method;
method = myObject.getClass().getMethod("map+"activemap"+method", param1.class, param2.class, ..);
method.invoke(object, arg1, arg2,...);