31

説明されている(IMHO、奇妙な)動作を示すSSCCEを次に示します

public class Test {

   public static void print(int param) {
       System.out.println("int");
   }

   public static void print(float param) {
       System.out.println("float");
   }

   public static void print(Long param) { //<--Wrapper type
       System.out.println("Long");
   }
   public static void main(String[] args) {
       long param = 100L;
       print(param);  // output == float
   }
} 

なぜJavaはそれをするのですか?

4

4 に答える 4

31

Java言語仕様はそれについて非常に明確です(強調は私のものです):

15.12.2 コンパイル時のステップ 2: メソッド シグネチャの決定

[...]

  1. 最初のフェーズ (§15.12.2.2) は、ボックス化またはボックス化解除の変換を許可せずにオーバーロードの解決を実行します [...] このフェーズで適用可能なメソッドが見つからない場合、処理は 2 番目のフェーズに進みます。[...]

  2. 2 番目のフェーズ (§15.12.2.3) は、ボックス化とボックス化解除を許可しながら、過負荷の解決を実行します [...]

  3. 第 3 フェーズ (§15.12.2.4) では、オーバーロードを可変アリティ メソッド、ボックス化、およびボックス化解除と組み合わせることができます。

つまり、最初のステップのみprint(int)であり、print(float)適切な場合があります。後者は一致し、それ以上の調査は行われません。


このようなルールの理由は、JLS でも説明されています。

これにより、Java SE 5.0 より前の Java プログラミング言語で有効だった呼び出しが、可変アリティ メソッド、暗黙的なボックス化および/またはボックス化解除の導入の結果として、あいまいであると見なされないことが保証されます。

Testクラスが Java 1.4 に対してコンパイルされているとします(オートボクシングの前)。その場合、それは明らかです:引数と完全に互換性がないため、選択する必要があります( toが安全であると見なされ、暗黙的である可能性があるprint(float)理由に同意すると仮定します...)。longfloatprint(Long)long

後で、Java 5+ に対して同じコードをコンパイルします。コンパイラは次のことができます。

  • このコンテキストではprint(Long)、より「明白な」ものとして選択してください。したがって、Java 5 にアップグレードすると、プログラムの動作が異なります...

  • 呼び出しがあいまいであるため、コンパイル エラーが発生します。したがって、以前は正しいコードが Java 5 でコンパイルされなくなりました (AFAIR は決して当てはまりません)。

  • ...または古いセマンティクスを保持し、Java 1.4 と同じメソッドを呼び出す

print(float)Java 1.4 では が選択されていたため、 が使用されている理由が理解できたはずです。そして、Java は下位互換性がなければなりません。

于 2013-01-27T17:20:10.773 に答える
12

選択floatする理由Longは、オートボクシングが後で追加され、下位互換性の理由から、常に行っていたのと同じ呼び出しを行う必要があるためです。

于 2013-01-27T17:51:45.250 に答える
7

Tomasz Nurkiewicz は仕様の関連部分 ( Java SE 7 JLSの 15.12.2 ) を指していますが、なぜそれを行うのでしょうか? 下位互換性のために、1.4 以前を対象とするソース コードは、オーバーロードされた同じメソッドを引き続き呼び出す必要があります。したがって、1.5 の機能は無視する必要があり、そうしないとコードがコンパイルされない場合にのみ、オートボクシングを考慮する必要があります。

からlongへの変換floatが暗黙的に行われる理由については、疑わしい設計上の選択です。

于 2013-01-27T17:35:17.100 に答える
5

ドキュメントを見る

第5章 コンバージョンとプロモーション

5.1.2. プリミティブ変換の拡大

プリミティブ型に対する 19 の特定の変換は、拡張プリミティブ変換と呼ばれます。

  • byte から short、int、long、float、または double
  • short から int、long、float、または double
  • char から int、long、float、または double
  • int から long、float、または double
  • フロートまたはダブルまで長い
  • float から double

なので変換形式longfloatルールに沿っています。

于 2013-01-27T17:22:17.643 に答える