Java Enum Methods - return opposite direction enum

Skyler picture Skyler · Sep 19, 2013 · Viewed 154.1k times · Source

I would like to declare an enum Direction, that has a method that returns the opposite direction (the following is not syntactically correct, i.e, enums cannot be instantiated, but it illustrates my point). Is this possible in Java?

Here is the code:

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);
     }
}

Answer

Pshemo picture Pshemo · Sep 19, 2013

For those lured here by title: yes, you can define your own methods in your enum. If you are wondering how to invoke such non-static method, you do it same way as with any other non-static method - you invoke it on instance of type which defines or inherits that method. In case of enums such instances are simply ENUM_CONSTANTs.

So all you need is EnumType.ENUM_CONSTANT.methodName(arguments).


Now lets go back to problem from question. One of solutions could be

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;
    }

}

Now Direction.NORTH.getOppositeDirection() will return Direction.SOUTH.


Here is little more "hacky" way to illustrate @jedwards comment but it doesn't feel as flexible as first approach since adding more fields or changing their order will break our code.

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]; 
    }
}