152 lines
4.0 KiB
Plaintext
152 lines
4.0 KiB
Plaintext
== Why is this an issue?
|
|
|
|
Comparing a variable to multiple cases is a frequent operation. This can be done using a sequence of if-else statements. However, for many cases like enums or simple value comparisons, a `switch` statement is the better alternative. With Java 21, the `switch` statement has been significantly improved to support pattern matching and record pattern.
|
|
|
|
Using a `switch` statement instead of an if-else chain provides benefits like clearer code, certainty of covering all cases, and may even improve performance.
|
|
|
|
This rule raises an issue when an if-else chain should be replaced by a `switch` statement.
|
|
|
|
== How to fix it
|
|
|
|
Replace the chain of if-else with a switch expression.
|
|
|
|
=== Code examples
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,java,text,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
sealed interface Expression {}
|
|
record Plus(Expression left, Expression right) implements Expression {}
|
|
record Minus(Expression left, Expression right) implements Expression {}
|
|
record Div(Expression left, Expression right) implements Expression {}
|
|
|
|
int eval(Expression expr){
|
|
if(expr instanceof Plus plus){ // Noncompliant; should be replaced by a switch expression
|
|
return eval(plus.left) + eval(plus.right);
|
|
}else if(expr instanceof Div div){
|
|
return eval(div.left) / eval(div.right);
|
|
}else if(expr instanceof Minus minus){
|
|
return eval(minus.left) - eval(minus.right);
|
|
} else {
|
|
throw new IllegalArgumentException("Unknown expression");
|
|
}
|
|
}
|
|
----
|
|
|
|
[source,java,text,diff-id=2,diff-type=noncompliant]
|
|
----
|
|
enum Color{RED,GREEN,YELLOW}
|
|
|
|
String name(Color c){
|
|
if(c == Color.RED){ // Noncompliant; should be replaced by a switch expression
|
|
return "red";
|
|
}else if(c == Color.GREEN){
|
|
return "green";
|
|
}else if(c == Color.YELLOW){
|
|
return "yellow";
|
|
}else{
|
|
throw new IllegalArgumentException("Unknown color");
|
|
}
|
|
}
|
|
----
|
|
|
|
[source,java,text,diff-id=3,diff-type=noncompliant]
|
|
----
|
|
int points(int result){
|
|
if(result == 2){ // Noncompliant; should be replaced by a switch expression
|
|
return 10;
|
|
} else if(result == 3 || result==4 ){
|
|
return 20;
|
|
} else if (result == 5) {
|
|
return 50;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
----
|
|
|
|
[source,java,text,diff-id=4,diff-type=noncompliant]
|
|
----
|
|
class Circle{}
|
|
class Rectangle{}
|
|
class Square{}
|
|
|
|
String name(Object shape){
|
|
if (shape instanceof Circle) { // Noncompliant; should be replaced by a switch expression
|
|
return "circle";
|
|
} else if (shape instanceof Rectangle) {
|
|
return "rectangle";
|
|
} else if (shape instanceof Square) {
|
|
return "square";
|
|
} else {
|
|
throw new IllegalArgumentException();
|
|
}
|
|
}
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,java,text,diff-id=1,diff-type=compliant]
|
|
----
|
|
sealed interface Expression {}
|
|
record Plus(Expression left, Expression right) implements Expression {}
|
|
record Minus(Expression left, Expression right) implements Expression {}
|
|
record Div(Expression left, Expression right) implements Expression {}
|
|
|
|
int eval(Expression expr){
|
|
return switch(expr){
|
|
case Div(var left, var right) -> eval(left) / eval(right);
|
|
case Plus(var left, var right) -> eval(left) + eval(right);
|
|
case Minus(var left, var right) -> eval(left) - eval(right);
|
|
};
|
|
}
|
|
----
|
|
|
|
[source,java,text,diff-id=2,diff-type=compliant]
|
|
----
|
|
enum Color{RED,GREEN,YELLOW}
|
|
String name(Color c){
|
|
return switch(c){
|
|
case RED -> "red";
|
|
case GREEN -> "green";
|
|
case YELLOW -> "yellow";
|
|
};
|
|
}
|
|
----
|
|
|
|
[source,java,text,diff-id=3,diff-type=compliant]
|
|
----
|
|
int points(int result){
|
|
return switch(result){
|
|
case 2 -> 10;
|
|
case 3,4 -> 20;
|
|
case 5 -> 50;
|
|
default -> 0;
|
|
};
|
|
}
|
|
----
|
|
|
|
[source,java,text,diff-id=4,diff-type=compliant]
|
|
----
|
|
class Circle{}
|
|
class Rectangle{}
|
|
class Square{}
|
|
|
|
String name(Object shape){
|
|
return switch(shape){
|
|
case Circle c -> "circle";
|
|
case Rectangle r -> "rectangle";
|
|
case Square s -> "square";
|
|
default -> throw new IllegalArgumentException();
|
|
};
|
|
}
|
|
----
|
|
|
|
|
|
== Resources
|
|
* https://openjdk.org/jeps/440[Record Patterns]
|
|
* https://openjdk.org/jeps/441[Pattern Matching for switch]
|
|
* https://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html[The switch Statement]
|
|
|