Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How method-overloading and primitive types works?

I'm doing my Java class exercises. I have this code which contains an overloaded method:

class A {

    // Overloaded method
    public void f(int n, float x) {
        System.out.println("f(int n, float x) n = " + n + " x = " + x);
    }

    private void f(long q, double y) {
        System.out.println("f(long q, double y) q = " + q + " y = " + y);
    }

    public void f(double y1, double y2) {
        System.out.println("f(double y1, double y2) y1 = " + y1 + " y2 = " + y2);
    }

    public void g() {
        int n = 1;
        long q = 12;
        float x = 1.5f;
        double y = 2.5;
        System.out.println("--- dans g ");
        f(n, q);
        f(q, n);
        f(n, x);
        f(n, y);
    }
}

Main:

public static void main(String[] args){ 
    A a = new A() ;
    a.g() ;
    System.out.println ("--- dans main") ;
    int n=1 ; 
    long q=12 ; 
    float x=1.5f ; 
    double y = 2.5 ;

    a.f(n, q) ; // my problem is here
    a.f(q, n) ; 
    a.f(n, x) ; 
    a.f(n, y) ;  
}

When I call the method a.f(n,q) in main I expect an error, but it calls the method f(int n, float x) while my q is a long number and it's size is bigger then a float's size (8 byte / 4 byte) So I wonder how these primitive types works?

like image 398
Skander Jenhani Avatar asked Mar 05 '23 15:03

Skander Jenhani


2 Answers

Method invocations occupy a pretty length chunk of the spec. To summarize, the compiler proceeds as follows:

  1. Identify classes on which the method might be invoked.
  2. Identify methods on those classes which might be invoked.
  3. If more than one method was identified, pick the most specific one.

Step 2 is the most interesting one here: this proceeds in a number of steps. To summarize:

  1. If there is a non-varargs method on the class with the exact same parameter types (strict invocation), choose that.
  2. If there is a non-varargs method on the class with parameter types for which automatic conversions from the actual parameters (loose invocation), choose that.
  3. If there is a varargs method on the class with parameter types that match with automatic conversion, choose that.

You're supplying parameters that don't exactly match any of the parameter types of the overloads, so you need check if you can convert that parameters to allow strict invocation. The conversions in strict invocations are:

  • an identity conversion (§5.1.1)
  • a widening primitive conversion (§5.1.2)
  • a widening reference conversion (§5.1.5)

An int can be converted by identity conversion to int. A long can be converted by widening primitive conversion to a float.

Hence f(int, float) is applicable.

f(long, double) and f(double, double) are also applicable, since int can be widened to long and double; and long can be widened to double.

However, these are less specific than f(int, float), since int can be widened to long and double, and float can be widened to double. Hence, by the informal intuition laid out in JLS Sec 15.12.2.5, these methods are less specific than f(int, float). As such, f(int, float) is the one that is invoked.

like image 101
Andy Turner Avatar answered Mar 16 '23 07:03

Andy Turner


longs can be converted to float without raising errors. But you may lose precision.

For details see the specs.

like image 24
Federico klez Culloca Avatar answered Mar 16 '23 07:03

Federico klez Culloca