Mehdi Academic 2014
Mehdi Academic 2014

Reputation: 81

Java Casting in Method Overloading

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

Upvotes: 1

Views: 3158

Answers (5)

Woodrow
Woodrow

Reputation: 136

Floats are funny that way.. they always try to convert to doubles automatically. This code compiles, with floats at every turn.

    public class wood {
    public static void main(String[] args) {
        float x = 10.1f;
        float y = 10.2f;
        System.out.println("Sum of x and y = " + sum1((float)x, (float)y));
    }
    public static float sum1(float x, float y) {
        return (float)((float)x+(float)y);
    }
}

edit; note that using a cast operator outside of parenthesis will cast after what is inside of the parenthesis has computed. So;

System.out.println((int)(50.5 + 50.7));

will print out 101.

Within java, some data conversions are automatic, and others require cast operators.. simply put, java will automatically make widening conversions, while you will have to use a cast operator for narrowing conversions.

The hierarchy of primitive data types is as follows:

byte //1 byte (-128 through 127)

short //2 bytes (over 32,000 give/take from 0)

int //4 bytes (over 2billion give/take from 0)

long //8 bytes (over 9 quintillion (10^18) give/take from 0)

float //4 bytes (holds 7 decimal places)

double //8 bytes (holds 15 decimal places)

java will not make narrowing conversions automatically, because then data is at risk of being lost. Both byte and short will become ints automatically.

short s = 5;
byte b = 5;
short sum = s + b;  //this will cause an error!

s and b automatically make a widening conversion to an int, and an int cannot be assigned to a short without a cast operator.

short sum = (short)(s + b);

would be needed.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500225

TL;DR version of this answer:

  • Variables of primitive types never have a different type at execution-time to their compile-time. (A double is always a double, never a float, etc.)
  • Overload resolution (picking which method signature is used) is performed using the compile-time types of expressions
  • Method implementation of the picked signature is performed using the execution-time type of the target of the method call

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.

Upvotes: 11

roeygol
roeygol

Reputation: 5028

Try to add new function: public double sum1(double a, double b). It will solve your problem. And also, this kind of casting will cause loss of data.

Upvotes: 0

No, the actual type of the variables is double. The type of the constants that you're assigning to that double variable, which get promoted on assignment, is float.

Upvotes: 1

Eran
Eran

Reputation: 393781

Casting double to float may cause loss of data, since it's a narrowing conversion, and is therefore not done automatically by the compiler. You'll have to cast the variables to float explicitly if you want it to take place.

Upvotes: 3

Related Questions