正如评论中所指出的,有一些方法可以使用 java 的反射功能。 See this question for how to do that。也就是说,反射在 java 中是一种非常糟糕的风格,只有在你真的没有其他选择的情况下才应该使用。 Java 在 OO 风格的编程和静态类型检查以及使用反射方面的真正重要之处在于忽略了这两个重点。这样做可能会使您的代码变得同样复杂且更难调试。
如果没有反射,那么如果有问题的代码块只发生一次,你也能做到这一点。您必须在某处实现逻辑,可能涉及相同的 if-else/switch 块。但是,如果您发现自己在多个位置复制粘贴相同的 if-elseif-elseif-elseif.... 块,您可以做得更好。
如果type 是一个枚举,您可以将逻辑移动到枚举本身,这从OO 的角度来看非常好。考虑以下几点:
public enum Direction {
NORTH,
SOUTH,
EAST,
WEST
}
public class Foo {
public void bar(Direction d) {
//At some point we want some logic to depend on the vector dx,dy form of d
int dx = 0;
int dy = 0;
switch(d) {
case NORTH:
dy = -1;
break;
case SOUTH:
dy = 1;
break;
case EAST:
dx = 1;
break;
case WEST:
dx = -1;
break;
}
//Use the values in dx, dy
}
}
在项目周围复制粘贴此块显然是个坏主意。如果您添加了新方向,则必须返回每个此类块以添加正确的添加。从 OO 的角度来看,dx、dy 字段确实是枚举值的一部分,并且应该从一开始就是它的一部分。因此,我们可以将上面的内容更改为:
public enum Direction {
NORTH,
SOUTH,
EAST,
WEST;
public int getDX() {
switch(this) {
case WEST: return -1;
case EAST: return 1;
default: return 0;
}
}
public int getDY() {
switch(this) {
case NORTH: return -1;
case SOUTH: return 1;
default: return 0;
}
}
}
或者,(IMO)更好,将它们表示为一个字段
public enum Direction {
NORTH(0,-1),
SOUTH(0,1),
EAST(1,0),
WEST(-1,0);
private int dx;
private int dy;
private Direction(int dx, int dy) {
this.dx = dx;
this.dy = dy;
}
public int getDX() {
return dx;
}
public int getDY() {
return dy;
}
}
从那里我们可以直接在Foo.bar() 中直接使用这些方法,不需要任何逻辑:
public class Foo {
public void bar(Direction d) {
//can directly use d.getDX() and d.getDY()
}
}
如果删除了一层,您关于函数调用的问题是相同的。我们可以直接将开关添加到枚举中:
public enum Type {
VALUE_ONE, VALUE_TWO, ...
public void callFunc() {
switch(this) {
case VALUE_ONE:
callFunctionOne();
return;
case VALUE_TWO:
callFunctionTwo();
return;
//....
}
}
}
然后通过直接引用该函数来使用它:
Type t = //....
t.callFunc();
您甚至可以使用一些 java-8 的东西来将要调用的函数表示为一个字段
@FunctionalInterface
public interface Unit {
public void apply();
}
public enum Type {
VALUE_ONE(Foo::baz),
VALUE_TWO(Foo::baz2),
//...
private Unit funcToCall;
private Type(Unit u) {
this.funcToCall = u;
}
public void callFunc() {
funcToCall.apply();
}
}
如果type 不是枚举,您可以使用上述部分(但不是全部)选项。您仍然可以将您的开关逻辑集中到一个辅助方法/类中,并将控制权传递给它,而不是复制/粘贴。 type 应该代表的东西越多,你发现自己越想switch 越多,枚举就越有可能是正确的选择。