簡単な答え:int
Java はs とs をs とlong
s の両方に自動的に拡張できますが、Java は aよりも (メモリ フットプリントの点で) 小さいため、 a に拡張することを選択します。引数を に明示的にキャストすることで、メソッドのバージョンを呼び出すことができます。float
double
float
double
double
double
System.out.print(m((double)a1) + "," + m((double)b1));
長い答え: Java の各プリミティブ データ型にはサイズ (バイト単位で測定) があり、これにより、特定のプリミティブが保持できる情報量 (または値の範囲) が決まります。次の表は、Java のプリミティブ データ型の一部のサイズを示しています。
byte 1 byte
short 2 bytes
char 2 bytes
int 4 bytes
float 4 bytes
long 8 bytes
double 8 bytes
Java は、Java 言語仕様で明確に定義された規則に従って、特定の状況で自動的に値を「拡張」します。次の拡張プリミティブ変換は、Java によって自動的に実行されます。
byte
~short
、int
、long
、float
、またはdouble
short
、int
、long
、float
またはdouble
char
、int
、long
、float
またはdouble
int
、long
、float
またはdouble
long
float
または_double
float
にdouble
この状況に適用されるその他の規則は次のとおりです。
- 拡大によって、数値の全体的な大きさに関する情報が失われることはありません。
- 整数型から別の整数型に拡張しても、情報はまったく失われません。数値は正確に保持されます。
int
またはlong
値を にfloat
、または値を に拡張すると、精度が失わlong
れるdouble
可能性があります。
たとえば、Java は数値をまったく変更せずにanint
を aに安全に拡張できます。どちらも整数型であり、aは an より大きいためです(ルール 2 を参照)。Java は anを aに拡張することもできますが、精度が失われる可能性があります。以下のサンプル コードは、この精度の低下を示しています。long
long
int
int
float
public static void foo(float f) {
System.out.println(f);
}
public static void main(String[] args) {
int a = 123;
int b = 1234567890;
foo(a);
foo(b);
}
への最初の呼び出しはfoo(float)
、期待どおり「123.0」を出力します。int
値「123」は値「123.0」に拡張されますfloat
。2 番目の呼び出しでは "1.23456794E9" が出力されますが、これはルール 3 を考慮に入れると意味があります。値 "1234567940" は"1234567890"と同じ大きさですが、精度は低くなります。
ここで重要なもう 1 つの情報: 複数のオーバーロードされたメソッドが存在する場合、Java は、指定された引数を拡張できるように (メモリ フットプリントの観点から)最小のパラメーター タイプを持つメソッドを選択することによって、呼び出すメソッドを決定します。パラメータ タイプ。つまり、メソッドに渡す数値は、メソッドのパラメーターの型に拡張できる必要があり、複数のオーバーロードされたメソッドがその要件を満たす場合、Java はパラメーターの型が最小サイズのメソッドを選択します。
あなたの場合、 anint
と along
を 2 つのオーバーロードされたメソッドのいずれかに渡しています。Java はメソッドm(float)
をm(double)
調べて、どのメソッドを呼び出すかを決定します。anは aおよびaint
に拡張できますが、a (4 バイト) は a (8 バイト) よりも小さいため、Java は を呼び出すことを選択します。引数を指定してメソッドを呼び出す場合も同様です。 が選択されるのは、 aを拡張できる最小のデータ型であるためです。float
double
float
double
m(float)
long
float
long