Java言語仕様はそれについて非常に明確です(強調は私のものです):
15.12.2 コンパイル時のステップ 2: メソッド シグネチャの決定
[...]
最初のフェーズ (§15.12.2.2) は、ボックス化またはボックス化解除の変換を許可せずにオーバーロードの解決を実行します [...] このフェーズで適用可能なメソッドが見つからない場合、処理は 2 番目のフェーズに進みます。[...]
2 番目のフェーズ (§15.12.2.3) は、ボックス化とボックス化解除を許可しながら、過負荷の解決を実行します [...]
第 3 フェーズ (§15.12.2.4) では、オーバーロードを可変アリティ メソッド、ボックス化、およびボックス化解除と組み合わせることができます。
つまり、最初のステップのみprint(int)
であり、print(float)
適切な場合があります。後者は一致し、それ以上の調査は行われません。
このようなルールの理由は、JLS でも説明されています。
これにより、Java SE 5.0 より前の Java プログラミング言語で有効だった呼び出しが、可変アリティ メソッド、暗黙的なボックス化および/またはボックス化解除の導入の結果として、あいまいであると見なされないことが保証されます。
Test
クラスが Java 1.4 に対してコンパイルされているとします(オートボクシングの前)。その場合、それは明らかです:引数と完全に互換性がないため、選択する必要があります( toが安全であると見なされ、暗黙的である可能性があるprint(float)
理由に同意すると仮定します...)。long
float
print(Long)
long
後で、Java 5+ に対して同じコードをコンパイルします。コンパイラは次のことができます。
このコンテキストではprint(Long)
、より「明白な」ものとして選択してください。したがって、Java 5 にアップグレードすると、プログラムの動作が異なります...
呼び出しがあいまいであるため、コンパイル エラーが発生します。したがって、以前は正しいコードが Java 5 でコンパイルされなくなりました (AFAIR は決して当てはまりません)。
...または古いセマンティクスを保持し、Java 1.4 と同じメソッドを呼び出す
print(float)
Java 1.4 では が選択されていたため、 が使用されている理由が理解できたはずです。そして、Java は下位互換性がなければなりません。