Продвижение типа и перегрузка метода (несколько параметров) - PullRequest
0 голосов
/ 06 июня 2019

Какие факторы определяют, какой метод будет выполняться при наличии нескольких приемлемых методов из-за продвижения типа?

Вот пример кода

public class Demo {
  public static void main(String[] args) {
    byte a = 100;
    long b = 10000;
    test(a, b);
  }

  public static void test(long a, double b) {
    System.out.println("Method 2");
  }

  public static void test(int a, float b) {
    System.out.println("Method 1");
  }
}

Вывод: Method 1 как написано, но Method 2, если я закомментирую test(int a, float b)

Почему это? Это пытается сделать наименьшее количество продвижение типа? Он пытается продвинуть аргумент 1, а затем аргумент 2? Это основано на каком-то типе приоритета?

Я видел этот вопрос: Как работает перегрузка методов и типы примитивов? , который включает в себя выражение:

  1. Если было идентифицировано более одного метода, выберите наиболее конкретный.

Я прошу больше подробностей о том, как финальный метод, который будет выполнен, выбран среди всех возможных методов. Я знаю, что продвижение типов происходит, но если после продвижения типов есть несколько опций, как компилятор определяет окончательный метод? Другими словами, из приведенного выше утверждения, что является более конкретным ?

1 Ответ

1 голос
/ 07 июня 2019

Хотя вопрос и ответ, на который вы ссылались, уже в какой-то степени охватывают это, можно взглянуть на более конкретный случай здесь (каламбур). В частности, соответствующий «путь к решению», относящийся к (несколько сложному) описанию 15.12.2.5. Выбор наиболее специфического метода в JLS.

В разделе в первую очередь говорится:

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

Это уже очень полезно, потому что вы можете видеть, что все, что вы передаете методу test(int, float) , может также передаваться методу test(long, double). Итак, первый более конкретный.

Но, ссылаясь на спецификацию:

Один применимый метод m1 является более конкретным, чем другой применимый метод m2, для вызова с выражениями аргумента e1, ..., ek, если выполняется любое из следующих условий:

  • m2 не является универсальным, а m1 и m2 применимы при строгом или произвольном вызове, и где m1 имеет формальные типы параметров S 1 , ..., S n и m2 имеют формальные типы параметров T 1 , ..., T n , тип S i более конкретен, чем T i для аргумента ei для всех i (1 ≤ i ≤ n, n = k).

...

Тип S более специфичен, чем тип T для любого выражения, если S <: T </p>

Последнее относится к 4.10. Подтип раздел, где отношение супертипа :> указано как рефлексивное и транзитивное замыкание отношения прямого супертипа >1 и последний включает для примитивных типов

  • double> 1 float
  • long> 1 int

Таким образом, метод test(int, float) более специфичен, чем test(long, double), поскольку int является подтипом long, а float является подтипом double.


(Обратите внимание, что понятие «подтипы» здесь также применяется к примитивным типам, а не только к «наследованию между классами»)

...