我有一个问题,使用开关情况的instanceof对象:

例如:我的问题可以在Java中重现:

if(this instanceof A)
    doA();
else if(this instanceof B)
    doB();
else if(this instanceof C)
    doC():

如何使用switch…case实现它?


当前回答

这个怎么样?

switch (this.name) 
{
  case "A":
    doA();
    break;
  case "B":
    doB();
    break;
  case "C":
    doC();
    break;
  default:
    console.log('Undefined instance');
}

其他回答

While it is not possible to write a switch statement, it is possible to branch out to specific processing for each given type. One way of doing this is to use standard double dispatch mechanism. An example where we want to "switch" based on type is Jersey Exception mapper where we need to map multitude of exceptions to error responses. While for this specific case there is probably a better way (i.e. using a polymorphic method that translates each exception to an error response), using double dispatch mechanism is still useful and practical.

interface Processable {
    <R> R process(final Processor<R> processor);
}

interface Processor<R> {
    R process(final A a);
    R process(final B b);
    R process(final C c);
    // for each type of Processable
    ...
}

class A implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

class B implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

class C implements Processable {
    // other class logic here

    <R> R process(final Processor<R> processor){
        return processor.process(this);
    }
}

然后在任何需要“开关”的地方,你可以这样做:

public class LogProcessor implements Processor<String> {
    private static final Logger log = Logger.for(LogProcessor.class);

    public void logIt(final Processable base) {
        log.info("Logging for type {}", process(base));
    }

    // Processor methods, these are basically the effective "case" statements
    String process(final A a) {
        return "Stringifying A";
    }

    String process(final B b) {
        return "Stringifying B";
    }

    String process(final C c) {
        return "Stringifying C";
    }
}

如果您可以操作公共接口,您可以在枚举中添加,并让每个类返回唯一的值。您不需要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块仍然可以工作。

如果需要通过“this”对象的类类型“切换”,这个答案是最好的https://stackoverflow.com/a/5579385/2078368

但如果你需要将“switch”应用于任何其他变量。我建议另一种解决办法。定义以下接口:

public interface ClassTypeInterface {
    public String getType();
}

在你想要“切换”的每个类中实现这个接口。例子:

public class A extends Something implements ClassTypeInterface {

    public final static String TYPE = "A";

    @Override
    public String getType() {
        return TYPE;
    }
}

之后,你可以用以下方式使用它:

switch (var.getType()) {
    case A.TYPE: {
        break;
    }
    case B.TYPE: {
        break;
    }
    ...
}

你唯一需要关心的是——在实现ClassTypeInterface的所有类中保持“类型”的唯一性。这不是一个大问题,因为在任何交集的情况下,您都会收到“switch-case”语句的编译时错误。

我个人比较喜欢下面的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");
            });

将输出:

YYyy

示例代码使用字符串,但您可以使用任何对象类型,包括Class。例如:. 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);
}

创建一个带有类名的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;
        }
    }
}

希望这能有所帮助。