首页 > 解决方案 > 使用两个实例变量在对象上切换大小写

问题描述

在 Java 中是否可以使用对象而不是原始类型来使用 switch-case 语句?

我有一个场景,我有很多 2d 位置 (x,y),我希望它们每个在被触发后表现不同。

例如,我想:

Pos pos = getNextPos();

switch (pos) {
    case new Pos(1, 2):
        // do something
        break;
    case new Pos(9, 7):
        // do something else...
        break;
    etc...
}

也许

Pos pos = getNextPos();
Pos[] listOfPos = getListOfPos();

switch (pos) {
    case listOfPos[0]:
        // do something
        break;
    case listOfPos[1]:
        // do something else...
        break;
    etc...
}

我还在我的Pos类中实现了 .equals() 方法,只有当 x 和 y 都等于另一个对象时才返回 true。

类(具有自动生成的Posequals 和 hashCode):

public class Pos {
    public int x;
    public int y;

    public Pos(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Pos pos = (Pos) o;
        return x == pos.x && y == pos.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

我已经尝试了所有这些,但是在编译时我得到“不兼容的类型:Pos 不能转换为 int”。

标签: java

解决方案


使用 Java 8 和 lambda,您可以使用以下方法switch

class Foobar {
  private final Map<Pos, Consumer<Pos>> mapping;

  Foobar() {
    mapping = new HashMap<>();
    mapping.put(new Pos(1, 2), this::doSomething1);
    mapping.put(new Pos(5, 2), this::doSomething2);
  }

  private void doSomething1(Pos pos) { ... }
  private void doSomething2(Pos pos) { ... }

  public void handleNextPost() {
    Pos pos = getNextPos();
    Consumer<Pos> consumer = mapping.get(getNextPos());
    if (null != consumer) {
      consumer.accept(pos);
    }
  } 
}

顺便说一句,在字节码级别,a switchonString几乎与 a HashMap: a tableswitchusing the相同hashCode(),然后根据需要使用goto.

上面的代码很简单:

  • 我为您要执行的每个操作声明一个map包含。Pos
  • 每个动作都由一个方法实现Pos
  • 当您阅读时getNextPos(),您搜索Consumer处理所述位置。
  • Consumer一起调用nextPos

您可以在本地定义它,但您必须确保mapping不要每次都创建它。

如果您真的必须坚持使用switch,则不需要任何特别的东西:您正在使用intforPos x/y并且switch自然地致力于int

switch (pos.getX()) {
  case 0: switch (pos.getY()) {
    case 1: { // [0, 1]
      break;
    }
    case 3: { // [0, 3]
       break;
    }     
  }
  break;
  // ... and so on
}

这很容易使您的代码更难阅读,因此请避免使用它。

此外, amap不是为松散匹配量身定制的(例如:对 x = 1 的每个 Pos 采取的操作),您可能必须使用其他替代方法。


推荐阅读