Java Enum方法

Sky*_*ler 105 java enums enumeration

我想声明一个枚举方向,它有一个方法返回相反的方向(下面的语法不正确,即枚举不能实例化,但它说明了我的观点).这在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);
     }
}
Run Code Online (Sandbox Code Playgroud)

Psh*_*emo 194

对于那些通过标题引诱的人:是的,你可以在枚举中定义自己的方法.如果您想知道如何调用这种非静态方法,那么您可以像使用任何其他非静态方法一样进行操作 - 您可以在定义或继承该方法的类型实例上调用它.在枚举的情况下,这样的实例只是ENUM_CONSTANTs.

所以你需要的只是EnumType.ENUM_CONSTANT.methodName(arguments).


现在让我们回到问题的问题.解决方案之一可能是

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

}
Run Code Online (Sandbox Code Playgroud)

现在Direction.NORTH.getOppositeDirection()将回归Direction.SOUTH.


这里用一些"hacky"方式来说明@jedwards评论,但它并不像第一种方法那样灵活

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]; 
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我正准备掀起一个`.values()[ordinal()]`hack,但这种方法更加强大 (3认同)

Ami*_*ani 152

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

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

}
Run Code Online (Sandbox Code Playgroud)

  • 很好的主意!当您通常希望每个枚举值具有特定行为时,这也很好. (8认同)

Pik*_*ass 24

这有效:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 而不是返回null,抛出合适的RuntimeException的默认子句可能更好地表明在没有为新添加的方向定义相反的情况下存在程序员错误. (7认同)
  • 这需要调用者处理空值。它还要求维护者确保每次添加新的方向类型时都添加一个案例。请参阅 Amir Afghani 关于使用可以被每个枚举值覆盖的抽象方法的回答,这样您就永远不会有遗漏一个的风险,而且您不必担心处理 null。 (2认同)

Mak*_*oto 14

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

但它读起来不太好; 也许一个switch会更容易管理?

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();
}
Run Code Online (Sandbox Code Playgroud)


Bev*_*ynQ 5

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

 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;
 }
Run Code Online (Sandbox Code Playgroud)