Reputation: 5736
Consider the following enum construction:
public enum MyEnum {
ENUM_A(TYPE1), ENUM_B(TYPE2), ENUM_C(TYPE1), ENUM_D(TYPE1);
private static final String TYPE1 = "I am type 1";
private static final String TYPE2 = "This is type 2";
private final String type;
private MyEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
The code above cannot be compiled because the compiler is complaining about illegal forward reference
. Which I kinda understand why as the constants are defined after the enums.
However, one cannot move the constants above/before the enums definition as thats enum limitation/design that the enums definition must be the first thing within the enum class.
Now if the code is changed to :
public enum MyEnum {
ENUM_A(MyEnum.TYPE1), ENUM_B(MyEnum.TYPE2), ENUM_C(MyEnum.TYPE1), ENUM_D(MyEnum.TYPE1);
private static final String TYPE1 = "I am type 1";
private static final String TYPE2 = "This is type 2";
private final String type;
private MyEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
Then it seems to work.
My questions are: does the changed code come with any potential issue even though it compiles? why the change can workaround the compiler check? is this considered a standard way or a way to bypass the compiler check that may be fixed in the future?
Upvotes: 1
Views: 392
Reputation: 925
Alternatively, you could put the enum inside a regular class and declare the constants as class members alongside the enum.
public class ConstantTypes {
private static String type1 = "type 1"
private static String type2 = "type 2"
public enum Types {
A(type1) {},
B(type1) {},
C(type2) {},
D(type2) {};
private final String type;
private Types(String typ) {
type = typ;
}
public String getType() { return type; }
}
}
EDIT: To directly answer your questions, you aren't exactly "working around the compiler check" per se in your second code example. There you are accessing the static values "in a static way", whereas in the first example you are not. There are no potential issues I am aware of with your second example (other than perhaps readability), the code compiles, you are good.
Upvotes: 1
Reputation: 2490
There is somewhat of an issue, yes.
By circumventing the limitation of not using fields that are not yet declared (by referencing the class that declares these static fields, which could have not been the current class and therefore bypasses the compiler's verification that this fields were already declared), you are using these fields before they exist.
It works fine in your example, because your fields happen to be constants: they're String literals declared final. Because of that the compiler knows their values at compile time and substitutes MyEnum.TYPE1 with the known constant value of MyEnum.TYPE1.
It will cease to work if you ever make your fields non-constant, yet it will still compile and only provide unwanted results at runtime. For example, try:
private static final String TYPE1 = new String("I am type 1");
Not a constant anymore => not working anymore.
Upvotes: 1
Reputation: 65811
This is a perfectly acceptable solution and I cannot think of any downsides other than the extra clutter.
If you want to remove the clutter you can use the fact that an interface
can hold constant values. This may break the principal of least surprise for some coders but I would accept it in my code.
private interface MyConstants {
String TYPE1 = "I am type 1";
String TYPE2 = "This is type 2";
}
public enum MyEnum implements MyConstants{
ENUM_A(TYPE1), ENUM_B(TYPE2), ENUM_C(TYPE1), ENUM_D(TYPE1);
private final String type;
private MyEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
Upvotes: 2