I have the enum as:
public enum EnumStatus {
PASSED(40L, "Has Passed"),
AVERAGE(60L, "Has Average Marks"),
GOOD(80L, "Has Good Marks");
private java.lang.String name;
private java.lang.Long id;
EnumStatus(Long id, java.lang.String name) {
this.name = name;
this.id = id;
}
public java.lang.String getName() {
return name;
}
public java.lang.Long getId() {
return id;
}
}
I have to get the Enum names(PASSED, AVERAGE, GOOD) using the ids only(40,60, 80). How do I do it?
Create a static method in your enum which searches in values (implicit method/member, don't know exactly which is it) and returns the corresponding value. For cases in which the method can not find a matching value, you should create a special entry, e.g. UNKNOWN, which you can return. This way, you do not have to return null, which is always a bad idea.
public static EnumStatus getById(Long id) {
for(EnumStatus e : values()) {
if(e.id.equals(id)) return e;
}
return UNKNOWN;
}
Btw - your code seems to be wrong. The bracket after GOOD seems to not belong there.
This can be done using a static map along with a static initializer:
public enum EnumStatus {
PASSED(40L, "Has Passed"),
AVERAGE(60L, "Has Average Marks"),
GOOD(80L, "Has Good Marks");
private static final Map<Long, EnumStatus> byId = new HashMap<Long, EnumStatus>();
static {
for (EnumStatus e : EnumStatus.values()) {
if (byId.put(e.getId(), e) != null) {
throw new IllegalArgumentException("duplicate id: " + e.getId());
}
}
}
public static EnumStatus getById(Long id) {
return byId.get(id);
}
// original code follows
private java.lang.String name;
private java.lang.Long id;
EnumStatus(Long id, java.lang.String name) {
this.name = name;
this.id = id;
}
public java.lang.String getName() {
return name;
}
public java.lang.Long getId() {
return id;
}
}
This will give an O(1) getById() method, and will automatically detect if you accidentally have duplicate ids in the enum.
You make this work as follows:
public static String fromId(long id) {
for (EnumStatus es : EnumStatus.values()) {
if (es.id.equals(id)) {
return es.getName();
}
}
throw new IllegalArgumentException();
}
public static EnumStatus getById(long id)
{
for (EnumStatus e : EnumStatus.values())
{
if (id == e.getId()) return e;
}
throw new IllegalArgumentException("oh no");
}
Add a method in your Enum and get it by passing ids.
public static ArrayList<EnumStatus> getEnumStatusById(ArrayList<Long> idList) {
ArrayList<EnumStatus> listById = new ArrayList();
for(EnumStatus es: EnumStatus.values()) {
if( idList.contains(es.getId())) {
listById.add(es);
}
}
return listById;
}
Define contract
/**
* Contract that will allow Types with id to have generic implementation.
*/
public interface IdentifierType<T> {
T getId();
}
Apply contract
public enum EntityType implements IdentifierType<Integer> {
ENTITY1(1, "ONE), ENTITY2(2, "TWO");
private Integer id;
private String name;
private EntityType(int id, String name) {
this.id = id;
this.name = name;
}
public static EntityType valueOf(Integer id) {
return EnumHelper.INSTANCE.valueOf(id, EntityType.values());
}
#Override
public Integer getId() {
return id;
}
}
Helper/Util
public enum EnumHelper {
INSTANCE;
/**
* This will return {#link Enum} constant out of provided {#link Enum} values with the specified id.
* #param id the id of the constant to return.
* #param values the {#link Enum} constants of specified type.
* #return the {#link Enum} constant.
*/
public <T extends IdentifierType<S>, S> T valueOf(S id, T[] values) {
if (!values[0].getClass().isEnum()) {
throw new IllegalArgumentException("Values provided to scan is not an Enum");
}
T type = null;
for (int i = 0; i < values.length && type == null; i++) {
if (values[i].getId().equals(id)) {
type = values[i];
}
}
return type;
}
}
Nihal, you have got a lot of replies answering how to find the right enum element.
But I have the feeling you wanted also to have the name of the element like "PASSED" instead of "Has Passed".
Please call for .name() to get "PASSED".
Extending the answer of Josua: getById(40L).name();
and EnumStatus.PASSED.getName() to get in your case "Has Passed".
This pattern can help you:
public interface Identifiable<T extends Number> {
#Nonnull
T getId();
}
public final class GettableById<K extends Number, V extends Enum<V> & Identifiable<K>> {
#Nonnull
private final Map<K, V> idToValue;
public GettableById(#Nonnull V[] values) {
this.idToValue = Arrays.stream(values)
.collect(Collectors.toUnmodifiableMap(Identifiable::getId, v -> v));
}
#Nonnull
public V getById(#Nonnull K id) {
var value = idToValue.get(id);
if (value != null) {
return value;
}
throw new NullPointerException("Cannot get value by id: %s".formatted(id));
}
}
public enum DataType implements Identifiable<Short> {
ANNUAL((short) 1), QUARTERLY((short) 2);
private static final GettableById<Short, DataType> companion = new GettableById<>(values());
#Nonnull
private final Short id;
public static DataType getById(Short id) {
return companion.getById(id);
}
DataType(#Nonnull Short id) {
this.id = id;
}
#Nonnull
#Override
public Short getId() {
return id;
}
}
Iterate over all the values and compare Id
for (EnumStatus enumStatus : EnumStatus.values()) {
if (..) {..}
}
Sometimes the enum's ordinal has a clear relationship with this kind of ids, enabling a neat way to get O(1) in these methods. In your code, it is clear that
EnumStatus.X = 40 + 20 * ordinal,
so you can leverage the static array that is generated under the hoods.
public static EnumStatus fromId(Long id) {
int index = (id - 40L) / 20L;
return values()[index];
}
Since Java 8 introduced Optional you can use it as a return type. Consider implementing like:
public static Optional<EnumStatus> fromId(Long id) {
for (EnumStatus e: values()) {
if (e.id.equals(id)) {
return Optional.of(e);
}
}
return Optional.empty();
}
Or using Stream API:
public static Optional<EnumStatus> fromId(Long id) {
return Stream.of(values())
.filter(e -> e.id.equals(id))
.findFirst();
}
In the book Effective Java 3rd Edition the author Joshua Bloch recommends an effective solution which also uses Optional as a return type:
private static final Map<String, Operation> stringToEnum =
Stream.of(values()).collect(
toMap(Object::toString, e -> e));
public static Optional<Operation> fromString(String symbol) {
return Optional.ofNullable(stringToEnum.get(symbol));
}
Bloch's reasoning for using Optional:
... note that the fromString method returns an Optional<Operation>. This
allows the method to indicate that the string that was passed in does not represent
a valid operation, and it forces the client to confront this possibility
Related
My two Type classes called SearchType and ResultcodeType need a parent class in an elegant way. How to design these two classes and a parent class both inherit from in an clean and code saving way?
public enum SearchType {
BARCODE(0),
TEXT(1);
SearchType(int i)
{
this.type = i;
}
private int type;
public static SearchType getType(int value) {
for (SearchType searchType : SearchType.values()) {
if (searchType.type == value)
return searchType;
}
throw new IllegalArgumentException("SearchType not found.");
}
public int getNumericType() {
return type;
}
}
and
public enum ResultcodeType {
RESULTS(0),
NO_RESULTS(1),
PROBLEMS(2),
NO_VALUE(-1);
ResultcodeType(int i)
{
this.type = i;
}
private int type;
public static ResultcodeType getType(int value) {
for (ResultcodeType resultcodeType : ResultcodeType.values()) {
if (resultcodeType.type == value)
return resultcodeType;
}
throw new IllegalArgumentException("ResultcodeType not found.");
}
public int getNumericType() {
return type;
}
}
Where do I use SearchType / ResultCodeType?
Layout Data Binding
<ImageView
app:srcCompat="#{item.searchType == SearchType.BARCODE ? #drawable/ic_barcode : #drawable/ic_one_loupe}"
/>
Room database converter class (where there is redundancy again). But for now room can't handle generic types in it's TypeConverter. So this will stay as is.
#TypeConverter
public static SearchType SearchTypeFromInt(Integer value) {
return SearchType.getType(value);
}
#TypeConverter
public static ResultcodeType ResultcodeTypeFromInt(Integer value) {
return ResultcodeType.getType(value);
}
POJO (with room annotation)
#NonNull
#ColumnInfo(name = "resultcode", defaultValue="-1")
private ResultcodeType mResultcode;
Since enums cannot have base classes, I think this is the closest you're going to get:
public interface Typed {
int getNumericType();
static <E extends Enum<E> & Typed> E getType(E[] values, int type) {
for (E value : values)
if (value.getNumericType() == type)
return value;
throw new IllegalArgumentException(values[0].getClass().getSimpleName() +
" not found: " + type);
}
}
public enum SearchType implements Typed {
BARCODE(0),
TEXT(1);
private final int type;
private SearchType(int type) {
this.type = type;
}
#Override
public int getNumericType() {
return this.type;
}
public static SearchType getType(int type) {
return Typed.getType(values(), type);
}
}
public enum ResultcodeType implements Typed {
RESULTS(0),
NO_RESULTS(1),
PROBLEMS(2),
NO_VALUE(-1);
private final int type;
private ResultcodeType(int type) {
this.type = type;
}
#Override
public int getNumericType() {
return this.type;
}
public static ResultcodeType getType(int type) {
return Typed.getType(values(), type);
}
}
Your enums could implement an interface and add default method.
For example:
interface Typed {
Typed getType(int value)
public enum ResultcodeType implements Typed {
public Typed getType(int value) {
for (ResultcodeType resultcodeType :
ResultcodeType.values()) {
if (resultcodeType.type == value)
return resultcodeType;
}
throw new IllegalArgumentException("ResultcodeType not found.");
}
....
}
I also suggest the following approach using a map instead of searching. In fact, all you need is the mapping. You wouldn't even need to supply a value. Note that you can't reference a static value from within a constructor so you have to build the map externally.
enum SearchType {
BARCODE(0), TEXT(1), UNKNOWN(-1);
static Map<Integer, SearchType> map =
Map.of(0, SearchType.BARCODE, 1, SearchType.TEXT);
SearchType(int i) {
this.type = i;
}
private int type;
public static SearchType getType(int value) {
return SearchType.map.getOrDefault(value, SearchType.UNKNOWN);
}
public int getNumericType() {
return type;
}
}
public static void main(String[] args) {
System.out.println(SearchType.getType(0));
System.out.println(SearchType.getType(1));
System.out.println(SearchType.getType(99));
}
I have a problem with enum in Java. I have an enum that starts from -1:
public enum AipType {
Unknown(-1),
None(0),
AipMod(1),
AipNoMod(2);
private final int id;
AipType(int id) {this.id = id;}
public int getValue() {return id;}
}
The problem is when I use this code to initialize a var of AipType
AipType at = AipType.getValues()[index];
where index is a number in the interval [-1,0,1,2] the -1 mess up the value.
i.e. 0 returns Unknown, 1 returns AipMod and 2 returns AipNoMod.
I used this implementation because I need to set manually the numeric value for each enum case. In other case I have a gap beetwen the values so I have the same problem: I cannot use values() and then access with [ ].
I tried to initialize in this way
AipType at = AipType(index);
but doesn't work.
Ideas ? Thanks...
We don't know what the getValues() method you're using exactly doing. Is it supposed to be values().
Anyway, you can always add a static method in your enum, which returns the correct enum instance for that value, and invoke it wherever you need it:
public enum AipType {
Unknown(-1),
None(0),
AipMod(1),
AipNoMod(2);
private final int id;
AipType(int id) {this.id = id;}
public int getValue() {return id;}
public static AipType fromValue(int id) {
for (AipType aip: values()) {
if (aip.getValue() == id) {
return aip;
}
}
return null;
}
}
If you're invoking fromValue() too often, you might also want to cache the array returned by values() inside the enum itself, and use it. Or even better, a map would be a better idea.
Enum.getValues() returns an array of the enums based on the definition order in the enum class.
getValues() doesn't know about the id field or the getValue() method you have added to your enum.
What you could do instead of calling getValues()[-1] (by the way, you'll never be able to index an array in Java with -1) is to add a static function like:
static AipType getAipType(int id) {
for (AipType a : getValues()) {
if (a.getId() == id) return a;
}
throw new IllegalArgumentException("id=" + id + " does not exist");
}
Just have a Map<Integer, AipType> instead of using values(), and expose access to it via a method:
public enum AipType {
UNKNOWN(-1),
NONE(0),
MOD(1),
NO_MOD(2);
private static final Map<Integer, AipType> VALUE_TO_ENUM_MAP;
private final int value;
static {
VALUE_TO_ENUM_MAP = new HashMap<>();
for (AipType type : EnumSet.allOf(AipType.class)) {
VALUE_TO_ENUM_MAP.put(type.value, type);
}
}
private AipType(int value) {
this.value = value;
}
public int getValue() {
return id;
}
public static AipType forValue(int value) {
return VALUE_TO_ENUM_MAP.get(value);
}
}
That will be completely flexible about values - or you could still use an array and just offset it appropriately.
Can you declare your enum like below?
public enum AipType {
Unknown(-1),None(0),AipMod(1),AipNoMod(2);
private int value;
private AipType(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
public static AipType fromValue(int value) {
for (AipType at: values()) {
if (at.getValue() == value) {
return at;
}
}
return null;
}
};
And instantiate like:
AipType at = AipType.fromValue(-1);
If the ids are completely custom, the only chance you'd have would be to create a map and store the id->AipType mapping there.
Example:
public enum AipType {
... //enum definitions here
static Map<Integer, AipType> map = new HashMap<>();
static {
for( AipType a : AipType.values() ) {
map.put(a.id, a);
}
}
public static AipType typeById( int id ) {
return map.get(id);
}
}
Then call it like AipType.typeById(-1);.
I have a class called x which is a array list and needs to be sorted in Decreasing order by Value.
My Class-
public static class x
{
public int id;
public double value;
public x(int _id, double _value)
{
id = _id;
value = _value;
//System.out.println(Integer.toString(id));
}
public Integer getID(){
return id;
}
public double getValue(){
return value;
}
//Sorting
public static Comparator<x> getComparator(SortParameter... sortParameters) {
return new xComparator(sortParameters);
}
public enum SortParameter {
VAL_DESCENDING
}
private static class xComparator implements Comparator<x> {
private SortParameter[] parameters;
private xComparator(SortParameter[] parameters) {
this.parameters = parameters;
}
public int compare(x o1, x o2) {
int comparison;
for (SortParameter parameter : parameters) {
switch (parameter) {
case VAL_DESCENDING:
comparison = o2.id - o1.id;
if (comparison != 0) return comparison;
break;
}
}
return 0;
}
}
}
I Call it like:
cp = x.getComparator(x.SortParameter.VAL_DESCENDING);
Collections.sort(attr1, cp);
attr1 is my array list
Just for Reference I am following this
I am getting error:
cannot find symbol : variable cp
I am a newbie to java :(
try using Comparator<x> cp = x.getComparator(x.SortParameter.VAL_DESCENDING); to declare it. you can not use a variable until it is declared
This question already has answers here:
Convert from enum ordinal to enum type
(15 answers)
Closed 7 years ago.
I've read a lot about how obtain the corresponding name of an enum from its value using java, but no example seems to work for me! What is wrong?
public class Extensions {
public enum RelationActiveEnum
{
Invited(0),
Active(1),
Suspended(2);
private final int value;
private RelationActiveEnum(final int value) {
this.value = value;
}
}
}
and in another class I use:
int dbValue = supp.ACTIVE;
Extensions.RelationActiveEnum enumValue(dbValue);
String stringName = enumValue.toString(); //Visible
// OR
int dbValuee = supp.ACTIVE;
String stringValue = Enum.GetName(typeof(RelationActiveEnum), dbValue);
I should work, right? but it doesn't!!!! it tells me that dbValue cannote be cast to RelationActiveEnum...
Say we have:
public enum MyEnum {
Test1, Test2, Test3
}
To get the name of a enum variable use name():
MyEnum e = MyEnum.Test1;
String name = e.name(); // Returns "Test1"
To get the enum from a (string) name, use valueOf():
String name = "Test1";
MyEnum e = Enum.valueOf(MyEnum.class, name);
If you require integer values to match enum fields, extend the enum class:
public enum MyEnum {
Test1(1), Test2(2), Test3(3);
public final int value;
MyEnum(final int value) {
this.value = value;
}
}
Now you can use:
MyEnum e = MyEnum.Test1;
int value = e.value; // = 1
And lookup the enum using the integer value:
MyEnum getValue(int value) {
for(MyEnum e: MyEnum.values()) {
if(e.value == value) {
return e;
}
}
return null;// not found
}
Since your 'value' also happens to match with ordinals you could just do:
public enum RelationActiveEnum {
Invited,
Active,
Suspended;
private final int value;
private RelationActiveEnum() {
this.value = ordinal();
}
}
And getting a enum from the value:
int value = 1;
RelationActiveEnum enumInstance = RelationActiveEnum.values()[value];
I guess an static method would be a good place to put this:
public enum RelationActiveEnum {
public static RelationActiveEnum fromValue(int value)
throws IllegalArgumentException {
try {
return RelationActiveEnum.values()[value]
} catch(ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("Unknown enum value :"+ value);
}
}
}
Obviously this all falls apart if your 'value' isn't the same value as the enum ordinal.
You could create a lookup method. Not the most efficient (depending on the enum's size) but it works.
public static String getNameByCode(int code){
for(RelationActiveEnum e : RelationActiveEnum.values()){
if(code == e.value) return e.name();
}
return null;
}
And call it like this:
RelationActiveEnum.getNameByCode(3);
What you can do is
RelationActiveEnum ae = Enum.valueOf(RelationActiveEnum.class,
RelationActiveEnum.ACTIVE.name();
or
RelationActiveEnum ae = RelationActiveEnum.valueOf(
RelationActiveEnum.ACTIVE.name();
or
// not recommended as the ordinal might not match the value
RelationActiveEnum ae = RelationActiveEnum.values()[
RelationActiveEnum.ACTIVE.value];
By if you want to lookup by a field of an enum you need to construct a collection such as a List, an array or a Map.
public enum RelationActiveEnum {
Invited(0),
Active(1),
Suspended(2);
private final int code;
private RelationActiveEnum(final int code) {
this.code = code;
}
private static final Map<Integer, RelationActiveEnum> BY_CODE_MAP = new LinkedHashMap<>();
static {
for (RelationActiveEnum rae : RelationActiveEnum.values()) {
BY_CODE_MAP.put(rae.code, rae);
}
}
public static RelationActiveEnum forCode(int code) {
return BY_CODE_MAP.get(code);
}
}
allows you to write
String name = RelationActiveEnum.forCode(RelationActiveEnum.ACTIVE.code).name();
In my case value was not an integer but a String.
getNameByCode method can be added to the enum to get name of a String value-
enum CODE {
SUCCESS("SCS"), DELETE("DEL");
private String status;
/**
* #return the status
*/
public String getStatus() {
return status;
}
/**
* #param status
* the status to set
*/
public void setStatus(String status) {
this.status = status;
}
private CODE(String status) {
this.status = status;
}
public static String getNameByCode(String code) {
for (int i = 0; i < CODE.values().length; i++) {
if (code.equals(CODE.values()[i].status))
return CODE.values()[i].name();
}
return null;
}
If you want something more efficient in runtime condition, you can have a map that contains every possible choice of the enum by their value. But it'll be juste slower at initialisation of the JVM.
import java.util.HashMap;
import java.util.Map;
/**
* Example of enum with a getter that need a value in parameter, and that return the Choice/Instance
* of the enum which has the same value.
* The value of each choice can be random.
*/
public enum MyEnum {
/** a random choice */
Choice1(4),
/** a nother one */
Choice2(2),
/** another one again */
Choice3(9);
/** a map that contains every choices of the enum ordered by their value. */
private static final Map<Integer, MyEnum> MY_MAP = new HashMap<Integer, MyEnum>();
static {
// populating the map
for (MyEnum myEnum : values()) {
MY_MAP.put(myEnum.getValue(), myEnum);
}
}
/** the value of the choice */
private int value;
/**
* constructor
* #param value the value
*/
private MyEnum(int value) {
this.value = value;
}
/**
* getter of the value
* #return int
*/
public int getValue() {
return value;
}
/**
* Return one of the choice of the enum by its value.
* May return null if there is no choice for this value.
* #param value value
* #return MyEnum
*/
public static MyEnum getByValue(int value) {
return MY_MAP.get(value);
}
/**
* {#inheritDoc}
* #see java.lang.Enum#toString()
*/
public String toString() {
return name() + "=" + value;
}
/**
* Exemple of how to use this class.
* #param args args
*/
public static void main(String[] args) {
MyEnum enum1 = MyEnum.Choice1;
System.out.println("enum1==>" + String.valueOf(enum1));
MyEnum enum2GotByValue = MyEnum.getByValue(enum1.getValue());
System.out.println("enum2GotByValue==>" + String.valueOf(enum2GotByValue));
MyEnum enum3Unknown = MyEnum.getByValue(4);
System.out.println("enum3Unknown==>" + String.valueOf(enum3Unknown));
}
}
This is my take on it:
public enum LoginState {
LOGGED_IN(1), LOGGED_OUT(0), IN_TRANSACTION(-1);
private int code;
LoginState(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static LoginState getLoginStateFromCode(int code){
for(LoginState e : LoginState.values()){
if(code == e.code) return e;
}
return LoginState.LOGGED_OUT; //or null
}
};
And I have used it with System Preferences in Android like so:
LoginState getLoginState(int i) {
return LoginState.getLoginStateFromCode(
prefs().getInt(SPK_IS_LOGIN, LoginState.LOGGED_OUT.getCode())
);
}
public static void setLoginState(LoginState newLoginState) {
editor().putInt(SPK_IS_LOGIN, newLoginState.getCode());
editor().commit();
}
where pref and editor are SharedPreferences and a SharedPreferences.Editor
I am trying to create a scenario where by an enum constant in enum class A has associated sub enum class B and enum class C containing their own constants. The constants in enum class B and enum class C group subsets of constants from enum class D. Below is a basically what I am trying to achieve:
enum A {
CONST_1 ("const_1", B), // B is the associated enum
CONST_2 ("const_2", C); // C in the associated enum
private final String strVal;
private final Enum associatedEnum;
private A (String strVal, Enum associatedEnum) {
this.strVal = strVal;
this.associatedEnum = associatedEnum;
}
public Enum getAssociatedEnum() {
return this.associatedEnum;
}
public String toString() {
return this.strVal;
}
// Associated Enum contained subset of grouped constants
enum B {
CONST_3 (D.CONST_7.toString()),
CONST_4 (D.CONST_8.toString());
private final String strVal;
private B (String strVal) {
this.strVal = strVal;
}
public String toString() {
return this.strVal;
}
}
// Associated Enum contained subset of grouped constants
enum C {
CONST_5 (D.CONST_9.toString()),
CONST_6 (D.CONST_10.toString());
private final String strVal;
private C (String strVal) {
this.strVal = strVal;
}
public String toString() {
return this.strVal;
}
}
}
// Separate Enum containing all ungrouped constants
enum D {
CONST_7 ("const_7"),
CONST_8 ("const_8");
CONST_9 ("const_9"),
CONST_10 ("const_10");
private final String strVal;
private D (String strVal) {
this.strVal = strVal;
}
public String toString() {
return this.strVal;
}
}
Obviously this syntax doesn't work OOTB because you cannot pass classes in Java this way. But can anyone suggest a way in which I could achieve this?
I am hoping to use it to validate static structured groupings in a client-side application.
This should hopefully do what you want. I've included an example usage where it'll list the sub enum type values.
package a.b.c;
public class EnumsTest {
public enum A {
A1( B.class ),
A2( C.class );
private final Class<? extends Enum<?>> enumClazz;
A( final Class<? extends Enum<?>> enumClazz ) {
this.enumClazz = enumClazz;
}
public Enum<?>[] getSubEnumConstants() {
return enumClazz.getEnumConstants();
}
/**
* #param value
* #return Never null
* #throws IllegalArgumentException To be consistent with Enum.valueOf()
*/
public <T> Enum<?> valueOfSubEnum( final String value ) throws IllegalArgumentException {
for( Enum<?> enumInstance : getSubEnumConstants() ) {
if( enumInstance.name().equals( value ) ) {
return enumInstance;
}
}
throw new IllegalArgumentException( "valueOf for " + enumClazz.getName() + " could not be resoled with the value of " + value );
}
}
public enum B {
B1,
B2;
}
public enum C {
C1,
C2;
}
public static void main( String[] args ) {
for( A a : A.values() ) {
for( Enum<?> enumInstance : a.getSubEnumConstants() ) {
System.out.println( a.name() + ":" + enumInstance.name() );
}
}
Enum<?> valueOfSubEnum = A.A1.valueOfSubEnum( "B2" );
System.out.println( valueOfSubEnum.name() );
}
}
Note: If you want to lock the subtypes down to a specific set, you can make them implement an interface.
You can't declare a enum A with constructor private B (String strVal, Enum associatedEnum). You can declare others enum inside each other, but not like this.
This works for me, but I might have missed what you are trying to achieve:
public enum A {
A1(B.B1),
A2(C.C2);
private final Enum<?> e;
private A(Enum<?> e) {
this.e = e;
}
static enum B {
B1,
B2;
}
static enum C {
C1(D.D1.getId()),
C2(D.D2.getId());
private String id;
private C(String id) {
this.id = id;
}
}
}
enum D {
D1("abc"),
D2("def");
private final String id;
private D(String id) {
this.id = id;
}
public String getId() {
return id;
}
}