如何将Object类型的实例“动态”转换为其特定数据类型?

2022-09-04 01:00:00
public Object foo(int opt){
  if (opt == 0) return new String();
  else if (opt == 1) return new Integer(1);
  else if (opt == 2) return new Double(1);
  else if ...
  .. and many more
}

public void doSomething(String s){..}
public void doSomething(Integer i){..}
public void doSomething(Double d){..}
... and many more doSomething method

public static void main(String[] args){
  ...
  Object o = foo(x); //x is a value obtained during runtime, e.g. from user input

  //now I want to call doSomething method
  // (1)
  if (o instanceof String) doSomething((String) o);
  else if (o instanceof Integer) doSomething((Integer) o);
  else if (o instanceof Double) doSomething((Double) o);
  ...
  // (2)
}

有没有更好的方法来简化(1)所附的陈述...(2)?
Java Reflection有帮助吗?


答案 1

有效和干净地处理这个问题的最佳方法是让 foo 返回对象的持有者类。

abstract class Holder<T> {
    private final T object;

    protected Holder(T object) { this.object = object; }
    public T get() { return object; }
    public abstract void doSomething();
}

public Holder foo(int opt) {
    if (opt == 0) return new Holder<String>("") {
        public void doSomething() { }
    };
    else if (opt == 1) return new Holder<Integer>(1) {
        public void doSomething() { }
    };
    else if (opt == 2) return new Holder<Double>(1.0) {
        public void doSomething() { }
    };
    // many more
}

public static void main(String... args) throws IOException {
    Holder h  = foo(x); //x is a value obtained during runtime, e.g. from user input

    //now I want to call doSomething method
    h.doSomething();
}

答案 2

基本上,您希望在执行时执行重载解析 - 您将无法非常简单地做到这一点。

在某些情况下访客模式可以提供帮助,但我认为这里不会。我认为你要么被困在你在这里的代码中,要么被反射所困。我从来没有像我的一些同事那样热衷于访客模式 - 它总是感觉有点混乱 - 但值得一想。

你能使调用正确的重载,而不仅仅是返回值吗?这是知道正在构造的内容的代码位 - 如果您可以向它传递一个对象以使用适当的重载调用,那么您最终会在一个地方获得特定于类型的逻辑。foodoSomethingdoSomething

在Java 7中,在这种情况下,invokedynamic可能会很有用 - 当然C# 4中的类型会有所帮助 - 但我还没有研究过volpticaldynamic来肯定。dynamic


推荐