如何制作通用枚举旋转器?在此示例中,它将是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;
}
}
答案 0 :(得分:10)
尝试:
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];
}
}
答案 1 :(得分:5)
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;
}
};
}
答案 2 :(得分:0)
使用界面:
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);
}
答案 3 :(得分:0)
这不是对问题的直接回答,而是与您尝试做的不同的方法。
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();
答案 4 :(得分:0)
我认为使用序数值始终是一种脆弱的方法,因为它依赖于位置,使用values()
或class.getEnumConstants()
。
答案 5 :(得分:0)
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);