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。
Pos
类(带有自动生成的 equals 和 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 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);
}
}
}
顺便说一句,在字节码级别,String
上的 switch
几乎与 HashMap
相同:一个 tableswitch
使用 hashCode()
,然后根据需要使用 goto
转到下一条语句。
上面的代码很简单:
- 我声明一个
map
,其中包含每个Pos
您想要执行的操作。 - 每个操作都是通过采用
Pos
的方法实现的 - 当您阅读
getNextPos()
时,您会搜索处理所述位置的Consumer
。 - 使用
nextPos
调用Consumer
。
您可以在本地定义它,但必须确保不会每次都创建映射
。
如果您确实必须坚持使用 switch
,则不需要任何特殊的东西:您正在使用 int
来表示 Pos 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
}
这很容易使您的代码难以阅读,因此请避免这样做。
此外,map
并不是为松散匹配而定制的(例如:对 x = 1 的每个 Pos 采取的操作),您可能必须使用其他替代方案。
关于java - 在具有两个实例变量的对象上切换大小写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59995065/