3

i was developing the below code

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));
}

Both results in output float, float , what the reason behind that please advise and how can I call double please advise thanks a lot.

2
  • 1
    by making the type of the variable being passed double :) Commented Apr 29, 2012 at 5:43
  • it's expected to get unexpected results when you pass unexpected type of values as arguments :) Commented Apr 29, 2012 at 6:25

4 Answers 4

7

Short answer: Java can automatically widen ints and longs to both floats and doubles, but Java will choose to widen to a float because it is smaller (in terms of memory footprint) than a double. You can call the double version of the method by explicitly casting the argument to a double:

System.out.print(m((double)a1) + "," + m((double)b1));

Long answer: Each primitive data type in Java has a size (measured in bytes), which determines how much information (or rather, what range of values) a given primitive can hold. The table below shows the sizes of some of Java's primitive data types:

byte     1 byte
short    2 bytes
char     2 bytes
int      4 bytes
float    4 bytes
long     8 bytes
double   8 bytes

Java will automatically "widen" values for you in certain situations, following some well-defined rules from the Java Language Specification. The following widening primitive conversions are performed by Java automatically:

  • byte to short, int, long, float, or double
  • short to int, long, float, or double
  • char to int, long, float, or double
  • int to long, float, or double
  • long to float or double
  • float to double

The other rules that are applicable to this situation are:

  1. Widening does not lose information about the overall magnitude of the numeric value.
  2. Widening from an integral type to another integral type does not lose any information at all; the numeric value is preserved exactly.
  3. Widening an int or long value to a float, or of a long value to a double may result in a loss of precision.

For example, Java can safely widen an int to a long without changing the numeric value at all, because both are integral types and a long is larger than an int (see rule 2). Java can also widen an int to a float, but there might be a loss of precision. The sample code below demonstrates this loss of precision.

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);
}

The first call to foo(float) prints "123.0" as expected. The int value "123" is widened to the float value "123.0". The second call prints "1.23456794E9", which makes sense when you take rule 3 into account. The value "1234567940" is the same magnitude as but less precise than "1234567890".

The other piece of information that is key here: when multiple overloaded methods are present, Java determines which method to call by choosing the method with the smallest parameter type (in terms of memory footprint) such that the given argument is capable of being widen to the parameter type. In other words, the number you pass to the method must be capable of being widened to the parameter type of the method, and if multiple overloaded methods satisfy that requirement, Java will choose the method whose parameter type is of the smallest size.

In your case, you are passing an int and a long to one of two overloaded methods. Java will look at methods m(float) and m(double) to determine which method to call. An int can be widened to a float and a double, but a float (4 bytes) is smaller than a double (8 bytes), so Java will choose to call m(float). The same is true when you call the method with a long argument: float is chosen because it's the smallest data type that a long can be widened to.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 exactly why Java "widens" a 8-byte long into a 4-byte float is a mystery to me. I suspect its historical.
4

If you want to call the double version, make it explicitly a double: m((double)a1)

Take a look at the JLS §8.4.9 - Method Overloading

Comments

3

Try

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

why are you creating an int and long to test it? Well, what is actually happening is that both parameters are converted to float by default.

Comments

1

how can I call double?

Use a double variable

double d = 3.3;
m(d);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.