Java枚举方法-返回反向枚举

Java枚举方法-返回反向枚举,java,enums,enumeration,Java,Enums,Enumeration,我想声明一个枚举方向,它有一个返回相反方向的方法。下面的方法在语法上不正确,也就是说,枚举无法实例化,但它说明了我的观点。这在Java中可能吗 代码如下: public enum Direction { NORTH(1), SOUTH(-1), EAST(-2), WEST(2); Direction(int code){ this.code=code; } protected int code;

我想声明一个枚举方向,它有一个返回相反方向的方法。下面的方法在语法上不正确,也就是说,枚举无法实例化,但它说明了我的观点。这在Java中可能吗

代码如下:

public enum Direction {

     NORTH(1),
     SOUTH(-1),
     EAST(-2),
     WEST(2);

     Direction(int code){
          this.code=code;
     }
     protected int code;
     public int getCode() {
           return this.code;
     }
     static Direction getOppositeDirection(Direction d){
           return new Direction(d.getCode() * -1);
     }
}

是的,我们一直这样做。返回的是静态实例,而不是新对象

 static Direction getOppositeDirection(Direction d){
       Direction result = null;
       if (d != null){
           int newCode = -d.getCode();
           for (Direction direction : Direction.values()){
               if (d.getCode() == newCode){
                   result = direction;
               }
           }
       }
       return result;
 }

对于那些被标题吸引的人:是的,你可以在你的枚举中定义你自己的方法。如果您想知道如何调用这样的非静态方法,那么您可以使用与任何其他非静态方法相同的方法来调用它——在定义或继承该方法的类型的实例上调用它。对于枚举,这些实例只是枚举常量

所以您只需要EnumType.ENUM_CONSTANT.methodNamearguments

现在让我们从问题回到问题。解决办法之一是

public enum Direction {

    NORTH, SOUTH, EAST, WEST;

    private Direction opposite;

    static {
        NORTH.opposite = SOUTH;
        SOUTH.opposite = NORTH;
        EAST.opposite = WEST;
        WEST.opposite = EAST;
    }

    public Direction getOppositeDirection() {
        return opposite;
    }

}
现在Direction.NORTH.getOppositeDirection将返回Direction.SOUTH

这里有一个更简单的方法来说明,但感觉不像第一种方法那么灵活,因为添加更多字段或更改它们的顺序会破坏我们的代码

public enum Direction {
    NORTH, EAST, SOUTH, WEST;

    // cached values to avoid recreating such array each time method is called
    private static final Direction[] VALUES = values();

    public Direction getOppositeDirection() {
        return VALUES[(ordinal() + 2) % 4]; 
    }
}

创建一个抽象方法,并让每个枚举值覆盖它。由于您在创建它时知道相反的情况,因此无需动态生成或创建它

但它读起来并不好;也许换一个更容易管理

public enum Direction {
    NORTH(1) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.SOUTH;
        }
    },
    SOUTH(-1) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.NORTH;
        }
    },
    EAST(-2) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.WEST;
        }
    },
    WEST(2) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.EAST;
        }
    };

    Direction(int code){
        this.code=code;
    }
    protected int code;

    public int getCode() {
        return this.code;
    }

    public abstract Direction getOppositeDirection();
}

对于这样的小枚举,我发现最具可读性的解决方案是:

public enum Direction {

    NORTH {
        @Override
        public Direction getOppositeDirection() {
            return SOUTH;
        }
    }, 
    SOUTH {
        @Override
        public Direction getOppositeDirection() {
            return NORTH;
        }
    },
    EAST {
        @Override
        public Direction getOppositeDirection() {
            return WEST;
        }
    },
    WEST {
        @Override
        public Direction getOppositeDirection() {
            return EAST;
        }
    };


    public abstract Direction getOppositeDirection();

}
这项工作:

public enum Direction {
    NORTH, SOUTH, EAST, WEST;

    public Direction oppose() {
        switch(this) {
            case NORTH: return SOUTH;
            case SOUTH: return NORTH;
            case EAST:  return WEST;
            case WEST:  return EAST;
        }
        throw new RuntimeException("Case not implemented");
    }
}
枚举有一个静态值方法,该方法返回一个数组,该数组按声明顺序包含枚举的所有值

因为北得1,东得2,南得3,西得4; 您可以创建一个简单的方程式来获得相反的方程式:


值+2%4

只需使用开关即可。你只有4个案例。顺便说一句,d.getCode*-1==-d.getCodeChapter 6在2E中,至少有可能是感兴趣的,并且是强烈推荐的。第2.1节已经解释了neatlyI将要发起一个.values[ordinal]黑客攻击的概念,但是这种方法更加健壮。不过,你如何使用它呢?这项技术叫什么?@Thufir若你们在询问这个方法,你们会如何使用它,然后像其他方法一样——你们用这个方法在类的实例上调用它。方向枚举类的实例有北、东、南、西,所以您可以只使用NORTH.getOppositeDirection,它将返回南。这种技术叫什么?如果您询问的是静态{…},那么它是,当类第一次加载时,它是初始化静态字段的同一进程的一部分时调用的代码。@Pshemo,我想知道如果静态块中设置的值需要从say属性文件中注入,上面代码的Spring版本会是什么样子。好主意!当您通常希望每个枚举值都有特定的行为时,这也很好。与其返回null,不如使用引发适当RuntimeException的默认子句来指示没有为新添加的方向定义对立面时出现程序员错误。这要求调用方处理null。它还要求维护人员确保每次添加新的方向类型时都添加一个案例。请参阅Amir Afghani关于使用可由每个枚举值覆盖的抽象方法的回答,这样您就不会有丢失一个枚举值的风险,而且您不必担心处理null。为什么这是答案?您认为这将如何帮助未来的读者或其他相关人员在不做任何解释的情况下学习?虽然这段代码可能会回答这个问题,但提供关于如何和/或为什么解决这个问题的额外信息将提高答案的长期价值。记住,你是在将来回答读者的问题,而不仅仅是现在提问的人!请编辑您的答案以添加解释,并说明适用的限制和假设。提到为什么这个答案比其他答案更合适也没什么坏处。没有注释的代码读起来难吗?或者您是否需要一个javadoc专用于7行代码?此解决方案很脆弱,因为它取决于枚举值的顺序。如果将顺序改为字母顺序,那么您的巧妙公式将不再提供正确的相反方向。
public enum Direction {
    NORTH, EAST, SOUTH, WEST;

    public Direction getOppositeDirection(){
        return Direction.values()[(this.ordinal() + 2) % 4];
    }
}