The code below triggers S1905 (observed in SonarLint v4.0.0.2916)
It suggest I “Remove this unneccessary cast to T2”.
If I do the code does not compile.
public class MapByName<T1 extends Enum, T2 extends Enum>
implements EnumMapper<T1, T2> {
private final Class<T2> destClass;
public MapByName(Class<T2> destClass) {
this.destClass = destClass;
}
@Override
public T2 map(T1 src) {
return (T2) Enum.valueOf(destClass, src.name());
}
}
interface EnumMapper<T1, T2> {
T2 map(T1 src);
}
public class MapByName<T1 extends Enum, T2 extends Enum> implements EnumMapper<T1, T2> {
private final Class<T2> destClass;
public MapByName(Class<T2> destClass) {
this.destClass = destClass;
}
@Override
public T2 map(T1 src) {
return (T2) Enum.valueOf(destClass, src.name());
}
}
by javac11.0.3 or 1.8.0_202 as following
javac MapByName.java -Xlint:unchecked
results in
MapByName.java:13: warning: [unchecked] unchecked method invocation: method valueOf in class Enum is applied to given types
return (T2) Enum.valueOf(destClass, src.name());
^
required: Class<T>,String
found: Class<T2>,String
where T,T2 are type-variables:
T extends Enum<T> declared in method <T>valueOf(Class<T>,String)
T2 extends Enum declared in class MapByName
MapByName.java:13: warning: [unchecked] unchecked cast
return (T2) Enum.valueOf(destClass, src.name());
^
required: T2
found: Enum
where T2 is a type-variable:
T2 extends Enum declared in class MapByName
2 warnings
In other simpler words - T2 is “almost” the same what Enum.valuesOf returns, but not exactly.
So let’s first fix this by replacing T2 extends Enum on T2 extends Enum<T2> - same compilation will pass without any warnings.
After that T2 is exactly what Enum.valuesOf returns, so let’s remove cast - final code is
interface EnumMapper<T1, T2> {
T2 map(T1 src);
}
public class MapByName<T1 extends Enum, T2 extends Enum<T2>> implements EnumMapper<T1, T2> {
private final Class<T2> destClass;
public MapByName(Class<T2> destClass) {
this.destClass = destClass;
}
@Override
public T2 map(T1 src) {
return Enum.valueOf(destClass, src.name());
}
}