3

我有一个方法foo

void foo (String x) { ... }
void foo (Integer x) { ... }

我想从一个不关心参数的方法中调用它:

void bar (Iterable i) {
  ...
  for (Object x : i) foo(x); // this is the only time i is used
  ...
}

上面的代码抱怨foo(Object)没有定义,当我添加

void foo (Object x) { throw new Exception; }

然后bar(Iterable<String>)调用它而不是foo(String)抛出异常。

如何避免 和 有两个文本相同的bar(Iterable<String>)定义bar(Iterable<Integer>)

我以为我可以摆脱类似的事情

<T> void bar (Iterable<T> i) {
  ...
  for (T x : i) foo(x); // this is the only time i is used
  ...
}

但后来我得到cannot find foo(T)错误。

4

3 回答 3

2

您面临的问题是重载方法在编译时绑定。在您的示例中,编译器试图找出foo()要调用的方法。但是,您的示例中最强的静态类型x是 Object ,并且没有 method foo(Object),因此编译器说它无法调用适当的方法。

如果你添加foo(Object)方法,无论 x 的实际运行时类型是什么,你总是会调用该foo(Object)方法。

这个问题延伸到使用泛型。由于T可以是任何类型,因此您必须有一个泛型方法foo(T),否则您的代码将无法编译。但是,如果添加该方法,您将无法让这些方法区分不同的参数类型,因为 onlyfoo(T)将被调用。

解决此问题的唯一方法是逐案检查并像提出的其他答案一样进行强制转换。除非参数类型是您定义的类并且它们都可以实现公共接口。然后您可以执行以下操作:

interface ArgumentType {
   void callback(FooClass c);
}

class YourClassA implements ArgumentType {
    void callback( FooClass c ) {
         c.foo( this );
    }
}

FooClass仍然必须foo()为每个实现类提供一个方法ArgumentType,但是这样您就可以通过类型不可知的方式进行选择。

于 2012-06-19T21:13:49.863 回答
1

这样想:foo应该调用哪个版本的 ifx是 an Object

这就是JVM面临的问题。

如果你想要一个真正的多态方法,那么你需要显式地编写一个。然后,这样的方法可以Object通过自省检查它的实际类类型,然后调用适当的方法。

或者,您可以仔细看看有什么foo作用。它只是调用由定义的方法Object吗?如果是这样,只需创建一个void foo(Object x)满足必要条件的方法。

于 2012-06-19T21:12:44.423 回答
1

问题是您正在尝试查找foo(Object x),而 String 和 Integer 都是对象,并非所有对象都是 String 或 Integer,并且 java 不会缩小到正确的类。

我可能会建议创建一个方法,如:

void foo(Object o){
     if ( o instanceof String){
         String s = (String) o;
         //Deal with s
     } else if ( o instanceof Integer){
         Integer i = (Integer) o;
         //Deal with i
     }
}

此外,如果您仍然使用泛型,则不应在 bar 中传递原始迭代器

于 2012-06-19T21:13:56.273 回答