I have the methods overloading such as:
public int sum1(int a, int b)
{
int c= a+b;
System.out.println("The method1");
return c;
}
public float sum1(int a, float b)
{
float c= a+b;
System.out.println("The method2");
return c;
}
public double sum1(float a, float b)
{
double c= (double) a+b;
System.out.println("The method3");
return c;
}
From the main method, suppose we have
double x=10.10f;
double y=10.20f;
the apparent type for x and y is double, but the actual type is float. when I call
System.out.println(" the output is :"+cc.sum1(x,y));
the error in the compile-time.
The method sum1(int, int) in the type Class is not applicable for the arguments double, double).
where it should go to sum1 (i.e. method3) by casting double to float
TL;DR version of this answer:
double
is always a double
, never a float
, etc.)the apparent type for x and y is double, but the actual type is float
No, it's not. You've just got a conversion from the assigned float
literals to double
values. The actual values are double
.
Primitives don't work like objects - there's no idea of an int
value still being an int
inside a double
variable, for example.
It's simpler to take an example with integer types. Suppose we have:
byte b = 100;
int x = b;
The value of x
is the 32-bit integer representing the value 100. It doesn't "know" that it was originally assigned from a byte
value... there just happened to be a conversion from byte
to int
at the point of assignment.
Compare that with reference types:
String x = "hello";
Object y = x;
Here, the value of y
really is a reference to a String
object. That type information is preserved precisely because there's a whole object that can contain it, and because the value of the variable itself is only a reference. (The bits themselves don't need to change as part of the assignment - in a simple VM at least, they'll be the exact same bits in x
and y
, because they're referring to the same object.)
Even in that case, however, overload resolution occurs based on the compile-time type of the arguments, not their actual values at execution time. The only way that the execution-time type of a variable gets involved is with overriding based on the target of a method call. So if we have:
Foo f = new X();
Foo g = new Y();
Foo h = new Z();
f.someMethod(g, h);
... then the compiler will look for a method in Foo
which has two Foo
parameters (or Object
or other superclasses/interfaces) - the actual types of the objects involved are irrelevant. At execution time, however, if that method has been overridden in X
, then that override will be called due to the execution-time type of the object f
's value refers to.
See more on this question at Stackoverflow