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

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有帮助吗?     
已邀请:
有效和干净地处理这个问题的最好方法是让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();
}
    
基本上你想要在执行时执行重载决策 - 你不能简单地做到这一点。 在某些情况下,访客模式可以提供帮助,但我不认为它会在这里。我想你已经遇到了你在这里得到的代码,或者反思。我从来没有像一些同事那样热衷于访客模式 - 它总是感觉有点乱 - 但是值得一想。 你能让
foo
调用正确的
doSomething
超载而不仅仅是返回值吗?这是知道正在构造什么的代码 - 如果你可以通过适当的重载将一个对象调用
doSomething
,你最终会在一个地方找到特定于类型的逻辑。 在Java 7中,invokedynamic可能在这种情况下很有用 - 当然C#4中的
dynamic
类型会有所帮助 - 但是我还没有足够好地调查invokedynamic。     
这里的问题可能是关注点分离。 Java是一种面向对象的语言,它可能有助于以面向对象的方式尝试解决问题。在这种情况下,您可能会问为什么main应该关注什么类型的Object o。相反,您可能会考虑使用一组类,每个类都知道如何以自己的方式执行某些操作。
abstract class Thing {
   abstract void doSomething();
}

class IntegerThing extends Thing {
  public void doSomething() {  /*whatever*/ };
}

class FloatThing extends Thing  {
  public void doSomething() { /*whatever*/ };
}


//Then later:

int foo(int type) {
  if(type == 0) return new IntegerThing(0);
  if(type == 1) return new FloatThing(7.5);
  if(type == 3) return new StringThing("Florence");
}

int main(String args[]) {
   Thing something = foo(x);
   something.doSomething();
}
你的foo()方法实际上变成了一个工厂,从那时起你不再需要关心foo返回了什么样的东西。     
Java反射有所帮助,但缺少一些数据。此外,反射通常会抛出您需要捕获的许多已检查异常。 (我在代码后面列出了一个列表) 持有“doSomething”方法的对象是什么?在这个例子中,我使用变量名“someObject”来表示持有“doSomething”方法的对象。你需要用它代替更具感性的东西。 此外,只是一个警告,这将不会捕获派生类型,因此如果方法定义与给定的类型不匹配,您将获得一个方法未找到异常。
//now I want to call doSomething method
// (1)
Method method = someObject.getClass.getMethod("doSomething",new Class[] {o.getClass()});
method.invoke(someObject, new Object[] {o});
// (2)
警告:当以这种方式使用反射时,您需要处理以下异常:(顺便提一下,这不是一个不常见的列表,反射通常在异常方面非常嘈杂)
NoSuchMethodException - if a matching method is not found or if the name is "<init>"or "<clinit>". 
NullPointerException - if name is null
SecurityException - if access to the information is denied.
IllegalAccessException - if this Method object enforces Java language access control and the underlying method is inaccessible.
IllegalArgumentException - if the method is an instance method and the specified object argument is not an instance of the class or interface declaring the underlying method (or of a subclass or implementor thereof); if the number of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal parameter type by a method invocation conversion.
InvocationTargetException - if the underlying method throws an exception.
NullPointerException - if the specified object is null and the method is an instance method.
ExceptionInInitializerError - if the initialization provoked by this method fails.
    
在Java中执行此操作没有任何意义。 Java是静态类型的,如果你要动态地转换它,你必须有一个switch语句才能调用不同对象上的不同方法。 示例 - 如果您有一个字符串或一个int并且您想要“动态”转换它(没有开关),那么对于不需要不同代码的两个操作,您可以执行什么操作。 我想我是说如果你因为想要访问两个对象(不同方法)不同的东西而进行强制转换,那么如何在没有开关的情况下实际访问不同的方法呢? 一个例外可能是内在变量 - 对于那些你想要泛型的人来说,但是在类之外使用内部变量无论如何都是个坏主意。  哦,你真正想要的是让所有的类都实现相同的接口 - 然后你就不用了。 铸造应该是非常罕见的。     

要回复问题请先登录注册