方法重载和原始类型如何工作?

Ska*_*ani 3 java overloading primitive-types

我在做Java课程练习.我有这个包含重载方法的代码:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

主要:

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) ;  
}
Run Code Online (Sandbox Code Playgroud)

当我a.f(n,q)在main中调用该方法时,我期待一个错误,但是f(int n, float x)当我q是一个long数字并且它的大小比一个float大小(8字节/ 4字节)大时调用该方法所以我想知道这些原始类型是如何工作的?

And*_*ner 7

方法调用占用规范的相当长的一部分.总而言之,编译器如下进行:

  1. 标识可以调用该方法的类.
  2. 确定可能被调用的那些类的方法.
  3. 如果确定了多种方法,请选择最具体的方法.

步骤2是这里最有趣的一个:这将在许多步骤中进行.总结一下:

  1. 如果类上的非varargs方法具有完全相同的参数类型(严格调用),请选择该方法.
  2. 如果类上有非varargs方法,其参数类型可以从实际参数中自动转换(松散调用),请选择该方法.
  3. 如果类上的varargs方法具有与自动转换匹配的参数类型,请选择该方法.

您提供的参数与过载的任何参数类型都不完全匹配,因此您需要检查是否可以转换该参数以允许严格调用.严格调用的转换:

  • 身份转换(§5.1.1)
  • 扩展的原始转换(第5.1.2节)
  • 扩大参考转换(第5.1.5节)

一个int可以通过标识转换被转换int.阿long可转化加宽原语转换到一个float.

因此f(int, float)适用.

f(long, double)并且f(double, double)也适用,因为int可以扩大到longdouble; 并且long可以扩大到double.

然而,这些不是特定于f(int, float),因为int可以扩展到longdouble,并且float可以扩展到double.因此,通过JLS Sec 15.12.2.5中规定非正式直觉,这些方法的具体性不如f(int, float).因此,f(int, float)是被调用的那个.