[英]How do I write a generic Java enum rotator?
如何制作通用枚舉旋轉器? 在這個例子中,它將是next()
的通用版本。
public class TestEnum
{
enum Temperature { hot, cold };
public static void main(String[] args)
{
Temperature t = Temperature.hot;
Temperature t2 = next(t);
}
static Temperature next(Temperature t)
{
if (t.ordinal() == Temperature.values().length - 1)
return Temperature.values()[0];
else
return Temperature.values()[t.ordinal() + 1];
}
}
編輯:在評論中, @irreputable
提出了一個出色的解決方案。 如果你發布它作為答案我將選擇它是irreputable
。 您可能希望通過復制此答案來節省時間。
static <T extends Enum<T>> T next(T t)
{
int index = t.ordinal();
@SuppressWarnings("unchecked")
Enum<T>[] constants = t.getClass().getEnumConstants();
if (index == constants.length - 1)
{
@SuppressWarnings("unchecked")
T result = (T)constants[0];
return result;
}
else
{
@SuppressWarnings("unchecked")
T result = (T)constants[index + 1];
return result;
}
}
嘗試:
public class Test {
enum Temperature { hot, cold };
public static void main(String[] args) throws Exception
{
Temperature t = Temperature.hot;
Temperature t2 = next(t);
System.out.println(t2);
}
static <T extends Enum> T next(T t) throws Exception
{
Method values = t.getClass().getMethod("values");
if (t.ordinal() == ((T[])values.invoke(t)).length - 1)
return ((T[])values.invoke(t))[0];
else
return ((T[])values.invoke(t))[t.ordinal() + 1];
}
}
IMO依靠位置來思考“下一個”或“前一個”將是一個壞主意,就像在應用程序代碼中依賴ordinal()一樣糟糕。 讓你的枚舉確定如何進行旋轉會更有意義,這樣在中間添加新成員就不會搞砸了。
您可以嘗試兩種解決方案:確保創建的每個枚舉都隱式處理下一個智能,這提供了更大程度的靈活性或創建了一個通用的輪換策略,可供所有支持輪換但靈活性較低的枚舉使用。
方法1(更大的靈活性)
enum Direction1 {
EAST() {
@Override
public Direction1 next(Rotation rotation) {
return rotation == Rotation.CLOCKWISE ? SOUTH : NORTH;
}
},
WEST() {
@Override
public Direction1 next(Rotation rotation) {
return rotation == Rotation.CLOCKWISE ? NORTH : SOUTH;
}
},
SOUTH() {
@Override
public Direction1 next(Rotation rotation) {
return rotation == Rotation.CLOCKWISE ? WEST : EAST;
}
},
NORTH() {
@Override
public Direction1 next(Rotation rotation) {
return rotation == Rotation.CLOCKWISE ? EAST : WEST;
}
};
abstract Direction1 next(Rotation rotation);
static enum Rotation {
CLOCKWISE, ANTICLOCKWISE
};
}
方法2,更通用,靈活性更低
interface Rotatable {
// now it would be difficult to make next() method take a rotation
Rotatable next();
}
enum Direction2 implements Rotatable {
// assume clockwise rotation
EAST() {
@Override
public Direction2 next() {
return SOUTH;
}
},
WEST() {
@Override
public Direction2 next() {
return NORTH;
}
},
SOUTH() {
@Override
public Direction2 next() {
return WEST;
}
},
NORTH() {
@Override
public Direction2 next() {
return EAST;
}
};
}
我相信使用序數值總是一個脆弱的方法,因為它將依賴於position,使用values()
或class.getEnumConstants()
。
public <T extends Enum<T>> T rotate(T current, int increment) {
T[] values = current.getDeclaringClass().getEnumConstants();
int i = current.ordinal() + increment;
while (i<0) i+= values.length;
return values[i%values.length];
}
Temperature next = rotate(hot, 1);
Temperature prev = rotate(hot, -1);
Temperature nextNext = rotate(hot, 2);
使用界面:
public interface EnumInterface {
public EnumInterface[] values1();
public int ordinal1();
}
enum Temperature implements EnumInterface {
HOT,
COLD;
public EnumInterface[] values1() {
return values();
}
public int ordinal1() {
return ordinal();
}
}
static <T extends EnumInterface> T next(T t) {
if (t.ordinal1() == t.values1().length - 1)
return (T) t.values1()[0];
else
return (T) t.values1()[t.ordinal1() + 1];
}
public static void main(String[] args) {
Temperature t = Temperature.HOT;
Temperature t2 = next(t);
System.out.println(t2);
}
這不是問題的直接答案,而是與您嘗試做的不同的方法。
public interface<T extends Enum<T>> NextEnum {
T next();
}
public enum Temperature implements NextEnum<Temperature> {
hot, cold;
public Temperature next() {
if (ordinal() == Temperature.values().length - 1)
return Temperature.values()[0];
else
return Temperature.values()[ordinal() + 1];
}
}
對於實現NextEnum
所有枚舉,您可以使用next()
方法。 例如:
Temperature.hot.next();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.