Videos
Off the top of my head:
Enum<?> convertedValue = Enum.valueOf((Class<Enum>)type, value);
This will convert a string to an enum constant of the Enum class of type
Edit: Now that I have a computer handy, I can see what actually works. Either of the below cases ran correctly without compiler warnings:
Enum<?> convertedValueA = Enum.valueOf(type, value);
Enum<?> convertedValueB = Enum.valueOf(type.asSubclass(Enum.class), value);
The second one calls asSubClass() which would do a runtime check to ensure that type is some enum class, but the valueOf() method has to make that check anyway in order to work correctly.
The following gave me a compile error:
Enum<?> convertedValueC = Enum.valueOf((Class<? extends Enum <?>>)type, value);
java: Foo.java:22: <T>valueOf(java.lang.Class<T>,java.lang.String) in java.lang.Enum cannot be applied to (java.lang.Class<capture#134 of ? extends java.lang.Enum<?>>,java.lang.String)
The intricacies of casting to wildcard types confuses me so I've probably tried the wrong cast. Plus the fact that it has no runtime effect means that it's easy to get it wrong and never find out.
You can use
Class enumType = ....
String name = ....
Enum e = Enum.valueOf(enumType, name);
e.g.
import java.lang.annotation.*;
public class Main {
public static void main(String[] args) {
Class enumType = RetentionPolicy.class;
String name = "SOURCE";
Enum e = Enum.valueOf(enumType, name);
System.out.println(e);
}
}
prints
SOURCE
Option 1 is to use a private static nested class to hold the map:
public enum ExampleEnum {
EXAMPLE0(Example.example0),
EXAMPLE1(Example.example1),
EXAMPLE2(Example.example2);
public final Example identifier;
private static class MapHolder{
private static Map<Example, ExampleEnum> map = new HashMap<>();
}
private ExampleEnum(final Example identifier) {
MapHolder.map.put(this.identifier = identifier, this);
}
public ExampleEnum get(final Example identifier) {
return MapHolder.map.get(identifier);
}
}
Of course, this will compile under the hood to a syntetic class ExampleEnum$MapHolder, but in the source code it's "modular".
Option 2 is to iterate over values():
public ExampleEnum get(final Example identifier) {
for(ExampleEnum e : values()){
if(e.identifier == identifier){
return e;
}
}
throw new IllegalArgumentException(); // or return null if you want
}
Personally, I would prefer this, as it introduces no new entities purely as a workaround. As for "slow linear search", that is very much a premature optimization.
First, a "linear search" over 3 elements is actually going to be faster than using a HashMap. At what number it becomes slower would have to be tested; I'd actually bet money that it's higher than the average number of elements in a Java enum.
And even then, it's still a premature optimization. Not gonna matter unless that method gets called millions of times a second in a tight loop, which it very likely won't.
Oh, here's Option 3 for our lovers of functional programming:
public ExampleEnum get(final Example identifier) {
return Arrays.stream(values())
.filter(e->e.identifier==identifier)
.findFirst()
.orElseThrow();
}
IMO a wash with Option 2 in terms of code prettiness, probably a bit slower as well (still likely irrelevant).
For me I think the best way to create an enum in Java and get its value is by using interface and make your enum implement this interface, after that you can create your methods inside the enum. I will show you an example:
public interface InterfaceForEnumType {
String getCode();
String getMessage();
}
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum MyEnum implements IntarfaceForEnumType {
EXAMPLE1("example_1", "message_1"),
EXAMPLE2("example_2", "message_2"),
private String code;
private String message;
public static MyEnum getMyEnumByCode(final String code) {
for (final myEnum e : MyEnum.values()){
if (StringUtils.equals(e.getCode(), code)) {
return e;
}
}
return null;
}
}
I hope this will help.