3

私は以下のコードを開発していました

static String m(float i) {
    return "float";
}

static String m(double i) {
    return "double";
}

public static void main(String[] args) {
    int a1 = 1;
    long b1 = 2;
    System.out.print(m(a1) + "," + m(b1));
}

どちらの結果も出力 float 、 float になります。その背後にある理由を教えてください。また、 double を呼び出す方法を教えてください。どうもありがとうございました。

4

4 に答える 4

7

簡単な答え:int Java はs とs をs とlongs の両方に自動的に拡張できますが、Java は aよりも (メモリ フットプリントの点で) 小さいため、 a に拡張することを選択します。引数を に明示的にキャストすることで、メソッドのバージョンを呼び出すことができます。floatdoublefloatdoubledoubledouble

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 によって自動的に実行されます。

  • byteshortintlongfloat、またはdouble
  • shortintlongfloatまたはdouble
  • charintlongfloatまたはdouble
  • intlongfloatまたはdouble
  • longfloatまたは_double
  • floatdouble

この状況に適用されるその他の規則は次のとおりです。

  1. 拡大によって、数値の全体的な大きさに関する情報が失われることはありません。
  2. 整数型から別の整数型に拡張しても、情報はまったく失われません。数値は正確に保持されます。
  3. intまたはlong値を にfloat、または値を に拡張すると、精度が失わlongれるdouble可能性があります。

たとえば、Java は数値をまったく変更せずにanintを aに安全に拡張できます。どちらも整数型であり、aは an より大きいためです(ルール 2 を参照)。Java は anを aに拡張することもできますが、精度が失われる可能性があります。以下のサンプル コードは、この精度の低下を示しています。longlongintintfloat

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 doublefloatdoublem(float)longfloatlong

于 2012-04-29T07:11:48.317 に答える
4

バージョンを呼び出したい場合はdouble、明示的に double にします。 m((double)a1)

JLS §8.4.9 - メソッドのオーバーロードを見てください。

于 2012-04-29T05:43:35.887 に答える
3

試す

    System.out.print(m(1f)+","+ m(2d));

なぜあなたはそれをテストするために int と long を作成しているのですか? 実際に起こっていることは、両方のパラメーターがデフォルトで float に変換されることです。

于 2012-04-29T05:43:27.930 に答える
1

どうすればダブルを呼び出すことができますか?

double変数を使用する

double d = 3.3;
m(d);
于 2012-04-29T05:43:58.267 に答える