我有一个问题,使用开关情况的instanceof对象:
例如:我的问题可以在Java中重现:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
如何使用switch…case实现它?
我有一个问题,使用开关情况的instanceof对象:
例如:我的问题可以在Java中重现:
if(this instanceof A)
doA();
else if(this instanceof B)
doB();
else if(this instanceof C)
doC():
如何使用switch…case实现它?
当前回答
如果您想避免If (){} else If{}的冗长,您可以考虑将这个文件切换到kotlin,并将类似于开关的when表达式与is操作符结合使用。
在任何情况下,Kotlin和java文件都可以共存于一个项目中,并生成一个可以在JVM中运行的jar。
when (this) { //switch-like statement in kotlin supporting class-pattern-matching and smart casts via `is` operator.
is A -> doA()
is B -> doB()
is C -> doC()
}
其他回答
从Java 17开始,您可以对开关表达式(预览特性)JEP-406使用模式匹配。
public void doAction(Object o) {
return switch (o) {
case A a -> doA(a);
case B b -> doB(b);
case C c -> doC(c);
default -> log.warn("Unrecognized type of {}", o);
};
}
防护模式也可用:
public void doAction(Object o) {
return switch (o) {
case String s && !s.isBlank() -> handle(s);
};
}
你需要启用预览功能来使用它:java——enable-preview
如果您可以操作公共接口,您可以在枚举中添加,并让每个类返回唯一的值。您不需要instanceof或visitor模式。
对我来说,逻辑需要写在switch语句中,而不是对象本身。这就是我的解决方案:
ClassA、ClassB和ClassC实现了CommonClass
接口:
public interface CommonClass {
MyEnum getEnumType();
}
枚举:
public enum MyEnum {
ClassA(0), ClassB(1), ClassC(2);
private int value;
private MyEnum(final int value) {
this.value = value;
}
public int getValue() {
return value;
}
Impl:
...
switch(obj.getEnumType())
{
case MyEnum.ClassA:
ClassA classA = (ClassA) obj;
break;
case MyEnum.ClassB:
ClassB classB = (ClassB) obj;
break;
case MyEnum.ClassC:
ClassC classC = (ClassC) obj;
break;
}
...
如果你使用的是java 7,你可以为枚举设置字符串值,并且switch case块仍然可以工作。
在最近发布的Java 19中,这非常简单和有用: 创建接口,并具有名为makesomenoise()的方法,它接受动物参数。
void makeSomeNoise (Animal animal) {
switch (animal) {
case Dog dog → dog.bark();
case Cat catcat.meow();
default throw new RuntimeException ("WTH is it???");
}
}
创建一个带有类名的Enum。
public enum ClassNameEnum {
A, B, C
}
找到对象的Class名称。 在枚举上写一个开关案例。
private void switchByClassType(Object obj) {
ClassNameEnum className = ClassNameEnum.valueOf(obj.getClass().getSimpleName());
switch (className) {
case A:
doA();
break;
case B:
doB();
break;
case C:
doC();
break;
}
}
}
希望这能有所帮助。
不幸的是,这是不可能开箱即用的,因为开关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);
}
}
这样就可以像这样使用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
}