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>)と の 2 つのテキストが同一の定義を避けるにはどうすればよい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)。そうしないと、コードがコンパイルされません。ただし、そのメソッドを追加すると、 のみfoo(T)が呼び出されるため、これらのメソッドが異なる引数の型を区別する機能が失われます。

これを回避する唯一の方法は、ケースバイケースのチェックを行い、提案された他の回答のようにキャストすることです。引数の型が定義したクラスであり、それらがすべて共通のインターフェイスを実装できる場合を除きます。次に、次のようなことができます。

interface ArgumentType {
   void callback(FooClass c);
}

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

FooClassfoo()の実装クラスごとにメソッドが必要ArgumentTypeですが、このようにして、タイプにとらわれずに選択することができます。

于 2012-06-19T21:13:49.863 に答える
1

このように考えてください: が の場合、どのバージョンをfoo呼び出す必要xがありObjectますか?

これが JVM が直面する問題です。

真にポリモーフィックなメソッドが必要な場合は、明示的に記述する必要があります。そのようなメソッドは、Objectイントロスペクションを介して検査して、実際のクラスの型が何であるかを確認し、その後適切なメソッドを呼び出すことができます。

または、何が行われているかを詳しく調べることができますfoo。によって定義されたメソッドのみを呼び出していObjectますか? void foo(Object x)その場合は、必要な処理を行うメソッドを作成してください。

于 2012-06-19T21:12:44.423 に答える
1

問題はfoo(Object x)、文字列と整数の両方がオブジェクトであっても、すべてのオブジェクトが文字列または整数のいずれかであるとは限らず、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 に答える