oli*_*dev 249 java instanceof switch-statement
我有一个使用switch case for instanceof
object的问题:
例如:我的问题可以用Java重现:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
Run Code Online (Sandbox Code Playgroud)
如何使用switch...case
?
jmg*_*jmg 209
这是子类型多态性有助于的典型场景.请执行下列操作
interface I {
void do();
}
class A implements I { void do() { doA() } ... }
class B implements I { void do() { doB() } ... }
class C implements I { void do() { doC() } ... }
Run Code Online (Sandbox Code Playgroud)
然后,你可以简单的调用do()
上this
.
如果你不随意更改A
,B
和C
,你可以申请访问者模式来实现相同的.
Nic*_*ico 92
如果你绝对无法编码到接口,那么你可以使用枚举作为中介:
public A() {
CLAZZ z = CLAZZ.valueOf(this.getClass().getSimpleName());
switch (z) {
case A:
doA();
break;
case B:
doB();
break;
case C:
doC();
break;
}
}
enum CLAZZ {
A,B,C;
}
Run Code Online (Sandbox Code Playgroud)
se.*_*yev 34
以防万一有人会阅读它:
Java中的最佳解决方案是:
public enum Action {
a{
void doAction(...){
// some code
}
},
b{
void doAction(...){
// some code
}
},
c{
void doAction(...){
// some code
}
};
abstract void doAction (...);
}
Run Code Online (Sandbox Code Playgroud)
这种模式的好处是:
你就是这样(根本没有开关):
void someFunction ( Action action ) {
action.doAction(...);
}
Run Code Online (Sandbox Code Playgroud)如果你添加名为"d"的新Action,你必须使用imAction(...)方法
注意:这种模式在Joshua的Bloch"Effective Java(第2版)"中有所描述.
Nov*_*ata 32
只需创建一个Map,其中类是键,功能,即lambda或类似,是值.
Map<Class,Runnable> doByClass = new HashMap<>();
doByClass.put(Foo.class, () -> doAClosure(this));
doByClass.put(Bar.class, this::doBMethod);
doByClass.put(Baz.class, new MyCRunnable());
Run Code Online (Sandbox Code Playgroud)
//当然,重构一下只能初始化一次
doByClass.get(getClass()).run();
Run Code Online (Sandbox Code Playgroud)
如果您需要检查异常,而不是实现抛出异常的FunctionalInterface并使用它而不是Runnable.
Pav*_*vel 16
正如在顶部答案中所讨论的,传统的OOP方法是使用多态而不是切换.对于这个技巧,甚至有一个记录良好的重构模式:用多态替换条件.每当我达到这种方法时,我也想实现一个Null对象来提供默认行为.
从Java 8开始,我们可以使用lambdas和泛型来为我们提供一些函数式程序员非常熟悉的东西:模式匹配.它不是核心语言功能,但Javaslang库提供了一个实现.来自javadoc的示例:
Match.ofType(Number.class)
.caze((Integer i) -> i)
.caze((String s) -> new BigDecimal(s))
.orElse(() -> -1)
.apply(1.0d); // result: -1
Run Code Online (Sandbox Code Playgroud)
它不是Java世界中最自然的范例,因此请谨慎使用它.虽然泛型方法将使您不必对匹配值进行类型转换,但我们缺少一种标准方法来分解匹配的对象,例如Scala的case类.
Java 现在允许您以 OP 的方式进行切换。他们称其为 switch模式匹配。它目前处于草案阶段,但看看他们最近在交换机上投入了多少工作,我认为它会通过。JEP中给出的例子是
String formatted;
switch (obj) {
case Integer i: formatted = String.format("int %d", i); break;
case Byte b: formatted = String.format("byte %d", b); break;
case Long l: formatted = String.format("long %d", l); break;
case Double d: formatted = String.format("double %f", d); break;
case String s: formatted = String.format("String %s", s); break
default: formatted = obj.toString();
}
Run Code Online (Sandbox Code Playgroud)
或者使用他们的 lambda 语法并返回一个值
String formatted =
switch (obj) {
case Integer i -> String.format("int %d", i)
case Byte b -> String.format("byte %d", b);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
default -> obj.toString();
};
Run Code Online (Sandbox Code Playgroud)
不管怎样,他们一直在用开关做很酷的事情。
我知道这已经很晚了,但对于未来的读者来说......
注意上面仅基于A,B,C ...... 类的名称的方法:
除非你能保证A,B,C ......(Base的所有子类或实现者)都是最终的,否则A,B,C ......的子类将不会被处理.
即使if,elseif,elseif .. 方法对于大量子类/实现者来说速度较慢,但它更准确.
爪哇 7+
public <T> T process(Object model) {
switch (model.getClass().getSimpleName()) {
case "Trade":
return processTrade((Trade) model);
case "InsuranceTransaction":
return processInsuranceTransaction((InsuranceTransaction) model);
case "CashTransaction":
return processCashTransaction((CashTransaction) model);
case "CardTransaction":
return processCardTransaction((CardTransaction) model);
case "TransferTransaction":
return processTransferTransaction((TransferTransaction) model);
case "ClientAccount":
return processAccount((ClientAccount) model);
...
default:
throw new IllegalArgumentException(model.getClass().getSimpleName());
}
}
Run Code Online (Sandbox Code Playgroud)
getSimpleName
通过引入常量和使用完整的类名省略内部的字符串操作,您可以更快:
public static final TRADE = Trade.class.getName();
...
switch (model.getClass().getName()) {
case TRADE:
Run Code Online (Sandbox Code Playgroud)
你不能让 switch 只适用于 byte、short、char、int、String 和枚举类型(以及基元的对象版本,它还取决于你的 java 版本,Strings 可以switch
在 java 7 中使用)
像这样使用switch语句不是面向对象的方式.你应该使用多态的力量.简单写一下
this.do()
Run Code Online (Sandbox Code Playgroud)
之前已经设置了基类:
abstract class Base {
abstract void do();
...
}
Run Code Online (Sandbox Code Playgroud)
这是基类A
,B
和C
:
class A extends Base {
void do() { this.doA() }
}
class B extends Base {
void do() { this.doB() }
}
class C extends Base {
void do() { this.doC() }
}
Run Code Online (Sandbox Code Playgroud)
我个人喜欢以下 Java 1.8 代码:
mySwitch("YY")
.myCase("AA", (o) -> {
System.out.println(o+"aa");
})
.myCase("BB", (o) -> {
System.out.println(o+"bb");
})
.myCase("YY", (o) -> {
System.out.println(o+"yy");
})
.myCase("ZZ", (o) -> {
System.out.println(o+"zz");
});
Run Code Online (Sandbox Code Playgroud)
将输出:
YYyy
Run Code Online (Sandbox Code Playgroud)
示例代码使用字符串,但您可以使用任何对象类型,包括类。例如.myCase(this.getClass(), (o) -> ...
需要以下代码段:
public Case mySwitch(Object reference) {
return new Case(reference);
}
public class Case {
private Object reference;
public Case(Object reference) {
this.reference = reference;
}
public Case myCase(Object b, OnMatchDo task) {
if (reference.equals(b)) {
task.task(reference);
}
return this;
}
}
public interface OnMatchDo {
public void task(Object o);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,由于switch-case语句需要一个常量表达式,因此不可能开箱即用。为了克服这个问题,一种方法是在类名中使用枚举值,例如
public enum MyEnum {
A(A.class.getName()),
B(B.class.getName()),
C(C.class.getName());
private String refClassname;
private static final Map<String, MyEnum> ENUM_MAP;
MyEnum (String refClassname) {
this.refClassname = refClassname;
}
static {
Map<String, MyEnum> map = new ConcurrentHashMap<String, MyEnum>();
for (MyEnum instance : MyEnum.values()) {
map.put(instance.refClassname, instance);
}
ENUM_MAP = Collections.unmodifiableMap(map);
}
public static MyEnum get(String name) {
return ENUM_MAP.get(name);
}
}
Run Code Online (Sandbox Code Playgroud)
这样就可以使用这样的switch语句
MyEnum type = MyEnum.get(clazz.getName());
switch (type) {
case A:
... // it's A class
case B:
... // it's B class
case C:
... // it's C class
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
209445 次 |
最近记录: |