Как работает метод с перегрузкой и примитивные типы? - PullRequest
0 голосов
/ 31 января 2019

Я делаю упражнения в классе 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);
    }
}

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

Когда я вызываю метод a.f(n,q) в основном, я ожидаю ошибку, но он вызывает методf(int n, float x), в то время как мой q - это число long, и его размер больше, чем размер float (8 байт / 4 байта). Поэтому мне интересно, как работают эти примитивные типы?

Ответы [ 3 ]

0 голосов
/ 31 января 2019

Вызовы методов занимают довольно большую часть спецификации.Таким образом, компилятор выполняет следующие действия:

  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 может быть расширен до long и doublelong может быть расширен до double.

Однако они менее специфичны, чем f(int, float), поскольку int может быть расширен до long и double, а float можетбыть расширен до double.Следовательно, согласно неформальной интуиции , изложенной в JLS Sec 15.12.2.5 , эти методы менее специфичны, чем f(int, float).Таким образом, f(int, float) - это тот, который вызывается.

0 голосов
/ 31 января 2019

Следующие 19 конкретных преобразований примитивных типов называются расширяющимися примитивными преобразованиями:

байт в short, int, long, float или double

short в int, long, float,или удваивает

char до int, long, float или удваивает

int до long, float или удваивает

long до float или удваивает

floatудваивать

Расширяющиеся примитивные преобразования не теряют информацию об общей величине числового значения.

...

Преобразование целого или длинного значения в плавающее,или длинное значение, удваиваемое, может привести к потере точности, то есть результат может потерять некоторые из младших значащих битов значения.В этом случае результирующее значение с плавающей запятой будет правильно округленной версией длинного значения.

0 голосов
/ 31 января 2019

longs можно преобразовать в float без возникновения ошибок.Но вы можете потерять точность.

Подробнее см. характеристики .

...