Consider the following sscce
public enum Flippable
A (Z), B (Y), Y (B), Z (A);
private final Flippable opposite;
private Flippable(Flippable opposite) {
this.opposite = opposite;
}
public Flippable flip() {
return opposite;
}
}
This doesn't compile, because Z
and Y
haven't been declared to be allowed to be arguments of A
and B
's constructor.
Potential solution 1: Hardcoded Methods
public enum Flippable {
A {
public Flippable flip() { return Z; }
}, B {
public Flippable flip() { return Y; }
}, Y {
public Flippable flip() { return B; }
}, Z {
public Flippable flip() { return A; }
};
public abstract Flippable flip();
}
While functional, this seems stylistically quite gross. Though I can't put a finger on why this would be a real problem.
Potential solution 2: static loading
public enum Flippable {
A, B, Y, Z;
private Flippable opposite;
static {
for(Flippable f : Flippable.values()) {
switch(f) {
case A:
f.opposite = Z;
break;
case B:
f.opposite = Y;
break;
case Y:
f.opposite = B;
break;
case Z:
f.opposite = A;
break;
}
}
}
public Flippable flip() {
return opposite;
}
}
This is even more gross than the first solution, as the field is no longer final, and is vulnerable to reflection. Ultimately that is an obscure worry, but suggests a bad code smell.
Is there a way to do this that is essentially the same as the first example, but compiles properly?
The types of all fields of the enum are deeply immutable. For example, use ImmutableList and ImmutableSet instead of List and Set . Types are considered immutable if they are primitives, in a set of types that are built in to Error Prone (e.g. java.
Enum constants are final by definition. But variables referencing a particular constant may be reassigned, unless they're declared final .
An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.
Again perhaps not as pretty as you were looking for ...
public enum Flippable {
A, B, Z, Y;
static {
A.opposite = Z;
B.opposite = Y;
Y.opposite = B;
Z.opposite = A;
}
public Flippable flip() {
return opposite;
}
private Flippable opposite;
public static void main(String[] args) {
for(Flippable f : Flippable.values()) {
System.out.println(f + " flips to " + f.flip());
}
}
}
As you can see it's not possible due to enum constants are static and you could not initialize A
until Z
is not initialized.
So this trick should work:
public enum Flippable {
A ("Z"), B ("Y"), Y ("B"), Z ("A");
private final String opposite;
private Flippable(String opposite) {
this.opposite = opposite;
}
public Flippable flip() {
return valueOf(opposite);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With