質問: ""; sp.method(str); } } ``` ``` (class)Sub--(arg)Object ``` 処理の流れは次のようになっていると考えました。 1. コンパイル時 変数`sp`の型のクラスからメソッドを探す。 2. Superクラスでマッチするメソッドが見つかる。 3. 実引数の型は`String`だが コンパイル時点で 仮引数の型`Object`にキャストされる 4. 実行時 メソッドが変数`sp`中のインスタンスのクラスから探索される 5. `Sub`クラスでメソッド名がマッチするメソッドが二つ見つかる 6. 実引数に代入されたインスタンスではなく 実引数の型を仮引数の型と比較する。 7. このとき 実引数の型は`Object`にキャストされているので メソッドは`method(Object o)`が選ばれる という認識です。あっているでしょうか。 よろしくお願いいたします。
回答: ***1. 実行時にメソッドの探索がおこなわれるとき 実引数と仮引数の比較は、代入されたインスタンスのクラス ではなく 実引数の型を比較する。*** 誤りです。Javaではoverloading(多重定義)の解決は、コンパイル時に静的な型をもとに行われます。実行時の実引数の型ではありません。 ***2. 実引数は コンパイル時に 探索されて見つかったメソッドの仮引数の型に 暗黙的にキャストされる。*** 誤りとは言えませんが、これは、Java(や殆どのオブジェクト指向言語)で許されている数少ない暗黙の型変換の一つです。メソッド呼び出し時の実引数/仮引数に限らず、`Object`のサブクラスである`String`型の値は、`Object`型の変数や仮引数に代入可能です。いわゆる「上位型への変換(upcasting)」ですね。 あなたの書き方に合わせて「処理の流れ」を修正すると、こんな感じ。 処理の流れは次のようになっている 1. コンパイル時 変数spの型のクラスからメソッドを探す。 2. Superクラスでマッチするメソッドが見つかる。 このとき`sp`の型は`Super`なので、見つかるメソッドは`method(Object)`だけ 3. 実引数の型はStringだが コンパイル時点で 仮引数の型Objectにキャストされる 4. 実行時 メソッド **`method(Object)`が** 変数sp中のインスタンスのクラスから探索される 5. Subクラスでメソッド **シグニチャ** がマッチするメソッドが **オーバライドされているのが** 見つかる 6. ~~実引数に代入されたインスタンスではなく 実引数の型を仮引数の型と比較する。~~ 7. このとき **`Sub`では`method(Object)`がオーバライドされている** ~~実引数の型はObjectにキャストされている~~ので メソッドは **`Sub`側の** `method(Object)`が選ばれる `overload`の解決⇒コンパイル時(どのシグニチャのメソッドが呼ばれるかはコンパイル時に決まっている) `override`の解決⇒実行時(そのシグニチャのメソッドのどのクラスの定義が使われるかは実行時に決まる) とまとめられます。