I am trying to build a generic method which gets an enum
as an argument and processes some information.
But unfortunately, it doesn't work as I would like. Maybe you have some suggestions to improve my code and prevent the errors.
private static ProductSearchColumnRange extractAllColumnRangeFromEnum(ProductSearchColumn column,
Enum someEnum) {
return ProductSearchColumnRange.builder()
.column(column)
.range(Arrays.stream(someEnum.values())
.map(element -> new RangeOption(element.getValue(), element.name()))
.collect(Collectors.toList()))
.build();
}
I get the following error on the someEnum.values()
call:
Cannot resolve method
values()
inEnum
I get the following errors on the element.getValue()
and element.name()
calls:
Cannot resolve method
getValue()
Cannot resolve method
name()
The enums I need to use in the method extractAllColumnRangeFromEnum()
above all have the same structure.
For example, one of them look like this:
public enum DeploymentModelType {
PRIVATE("Private"),
HYBRID("Hybrid"),
PUBLIC("Public");
String value;
DeploymentModelType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
I know that I can prevent the error by using
private static ProductSearchColumnRange extractAllColumnRangeFromEnum(ProductSearchColumn column,
DeploymentModelType someEnum) {
...
}
But then my method would not be generic. I want to use this method for any of my enums.
CodePudding user response:
Since you need all the enum
elements to generate a list of RangeOption
objects, your method should expect as a parameter a Class<T>
of the enum, not a single element.
In order to access the enum constants, you can make use of the static method EnumSet.allOf()
of the EnumSet
. Which expects the enums Class<T>
as parameter.
In order to be able to invoke your custom method getValue()
you need to introduce an interface, let's say ModelType
, that will declare that method. In turn, DeploymentModelType
and other enums should implement this interface.
And you need to add a generic type parameter to the declaration of your method. It needs to be placed after modifiers (if any) and before the return type of the method.
In this case, generic type parameter has to be <T extends Enum<T> & ModelType>
. I.e. T
is a subtype of both java.lang.Enum
class and ModelType
interface.
for information on the syntax of generic methods, take a look at this tutorial
The code might look like that:
private static <T extends Enum<T> & ModelType>
ProductSearchColumnRange
extractAllColumnRangeFromEnum(ProductSearchColumn column,
Class<T> enumClass) {
return ProductSearchColumnRange.builder()
.column(column)
.range(EnumSet.allOf(enumClass).stream()
.map(element -> new RangeOption(element.getValue(), element.name()))
.collect(Collectors.toList()))
.build();
}
public enum DeploymentModelType implements ModelType {
// your code
}
public interface ModelType {
String getValue();
}
CodePudding user response:
the java.lang.Enum
don't have values()
method, this method is implicitly declared by compiler. It's mean that values()
method only exist in MyEnum.class
, can't found in MyEnum.java
.
More info about implicitly declared method and enum specifications can be found in https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.9