オーバーロードされたメソッドにバイト引数を渡す


12

私はいくつかのクイズからこのコードスニペットを取得し、IDEを使用して実行し、長い結果を取得しましたが、正しい答えはByte、Byteです。なぜ別の結果を得たのですか?質問はJDK 11に関連しています

public class Client {
    static void doCalc(byte... a) {
        System.out.print("byte...");
    }

    static void doCalc(long a, long b) {
        System.out.print("long, long");
    }

    static void doCalc(Byte s1, Byte s2) {
        System.out.print("Byte, Byte");
    }

    public static void main(String[] args) {
        byte b = 5;
        doCalc(b, b);
    }
}

編集:

コードはここで取得されました:Oracle認定の概要とサンプルの質問 (ページ:13、質問:5)


1
Byte b = 5;大文字のB ではないことを確認しますか?
Joop Eggen

4
long, longはJava8にも乗りすぎます。正直に言うと、答えを待っている理由もわかりません:)
sp00m

回答:


6

したがって、コンパイル時にメソッドシグネチャを決定するためのJava言語仕様を確認すると、それは明らかです。

  1. 最初のフェーズ(15.12.2.2)は、ボックス化またはボックス化解除の変換、または可変アリティメソッドの呼び出しの使用を許可せずに、過負荷の解決を実行します。このフェーズ中に該当するメソッドが見つからない場合、処理は第2フェーズに進みます。

  2. 2番目のフェーズ(15.12.2.3)では、ボクシングとアンボクシングを許可しながら過負荷解決を実行しますが、可変アリティメソッドの呼び出しは使用できません。このフェーズ中に該当するメソッドが見つからない場合、処理は3番目のフェーズに進みます。

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

したがって、上記のステップから、最初のフェーズで Javaコンパイラが一致するメソッドを見つけることは明らかですdoCalc(long a,long b)。メソッドdoCalc(Byte s1, Byte s2)は、呼び出し中にオートボクシングを必要とするため、優先順位が低くなります。


1
なぜに関してlong受け入れbyte、従うように思わ拡大プリミティブ変換docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2を。つまり、基本的には+widening -boxing -varargsそれ+widening +boxing -varargsから+widening +boxing +varargs
sp00m

@kboなぜ正しい答えだと思いますByte, Byteか?
アミットベラ

3
@kbo 正しい答えは間違っていると思います :)できれば著者にこの質問を指摘する価値があるかもしれません。
sp00m

3
@ sp00mこの質問はOracleのサンプルで見つかりました。編集された部分をご覧ください
kbo

@kboうわー...どうすればいいのかわからない!
sp00m

2

変換に関するJLSの章をお読みください。

あなたのケースで何が起こっているかというと、実行時に、JVMは拡大変換 を実行することを選択するbyte -> longということですRuntimeException

から呼ばれるボクシングに変換するbyteと、JVMが新しいオブジェクトをヒープに割り当てる必要があるため、OutOfMemoryErrorが発生する可能性があります。Byte

ラッパークラス(ブール、バイト、文字、ショート、整数、ロング、フロート、またはダブル)のいずれかの新しいインスタンスを割り当てる必要があり、十分なストレージが利用できない場合、ボクシング変換によってOutOfMemoryErrorが発生する可能性があります。

そのため、より安全なbyte -> long 拡大変換が推奨されます。


2
注意してください。(-128-127)のすべての値は内部的にキャッシュされるため、からbyteへのボクシングはをByte引き起こしません。ただし、他のタイプと同じではない可能性があるため、経験則として、拡大変換が優先されます。OutOfMemoryExceptionByte
Pavel Smirnov、

1

正しいオーバーロードを見つけるための順序は次のとおりです。

  1. パラメータの数
  2. ボクシング/アンボクシング
  3. 可変パラメータ

そう

  • もしbどこByte結果は次のようになりByte, Byte
  • 合格した場合new byte[] { b, b }、結果はになりますbyte, byte
  • 2バイトbを渡した場合、バイトからint、longへの拡張が可能であり、結果はlong, longです。
  • 長い、長い過負荷が取り除かれると、Byte, Byte結果が生じます。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.