在java中切换类型

新手上路,请多包涵

在我开始之前,我知道这个问题有很多建议替代方法的答案。我正在为这种特定方法寻求帮助,看它是否可行,如果不可能,类似的方法是否可行。

我有一个方法,它接受一个超类并根据传递的对象的类型调用一个方法。例如:

 public void handle(Object o){
  if (o instanceof A)
    handleA((A)o);
  else if (o instanceof B)
    handleB((B)o);
  else if (o instanceof C)
    handleC((C)o);
  else
    handleUnknown(o);

我无法修改子类型以覆盖 handle() 方法,正如 这个答案 所暗示的那样,因为我不拥有这些类。所以我只有 instanceof 方法。

我想使用 switch 语句而不是 if/else ,仅仅是因为它更整洁。我知道你只能打开基元和字符串,所以我要切换类名:

 switch(o.getClass().getCanonicalName()){
case "my.package.A":
  handleA((A)o);
  break;
case "my.package.B":
  handleB((B)o);
  break;
case "my.package.C":
  handleC((C)o);
  break;
default:
  handleUnknown(o);
  break;
}

这里的问题是规范名称非常长(如 12 个子包),我不能在 case 语句中调用 ClassName.class.getCanonicalName() 因为 Java 不允许这样做。所以我的下一个解决方案是枚举。这是我遇到问题的地方。

我希望我的代码看起来像这样:

 public enum Classes {
  A (A.getCanonicalName()),
  B (B.getCanonicalName()),
  C (C.getCanonicalName());
}

switch (o.getClass().getCanonicalName()){
case Classes.A:
  handleA((A)o);
  break;
case Classes.B:
  handleB((B)o);
  break;
case Classes.C:
  handleC((C)o);
  break;
default:
  handleUnknown(o);
  break;
}

但这不编译。我不确定为什么。我想要一些允许我切换类型而不必输入整个规范名称的方法。如果我这样做,我还不如只使用 if/elseinstanceof

注意 有几个类型具有相同的名称(内部类),所以 getSimpleName() 已经过时了。

原文由 ewok 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 344
1 个回答

这是一种根本不处理类名的方法,并且像 switch 语句一样快速调度:制作一个哈希映射以映射 Class<T> 对象到特定于类的处理程序,并使用地图代替 switch

 // Declare an interface for your polymorphic handlers to implement.
// There will be only anonymous implementations of this interface.
private interface Handler {
    void handle(Object o);
}
// Make a map that translates a Class object to a Handler
private static final Map<Class,Handler> dispatch = new HashMap<Class,Handler>();
// Populate the map in a static initializer
static {
    dispatch.put(A.class, new Handler() {
        public void handle(Object o) {
            handleA((A)o);
        }
    });
    dispatch.put(B.class, new Handler() {
        public void handle(Object o) {
            handleB((B)o);
        }
    });
    dispatch.put(C.class, new Handler() {
        public void handle(Object o) {
            handleC((C)o);
        }
    });
}
// This object performs the dispatch by looking up a handler,
// and calling it if it's available
private static void handle(Object o) {
    Handler h = dispatch.get(o.getClass());
    if (h == null) {
        // Throw an exception: unknown type
    }
    h.handle(o); // <<== Here is the magic
}

原文由 Sergey Kalinichenko 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题