Выбор метода перегрузки - PullRequest
0 голосов
/ 22 апреля 2019

Давайте рассмотрим пример

public class C {

  public void method(String s, Integer i, Object... o) {
    System.out.println("method(String s, Integer i, Object... o)");
  }

  public void method(Object o, Integer i) {
    System.out.println("method(Object o, Integer i)");
  }
}

Когда я выполняю

C c = new C();
c.method("1", 1);

Я ожидал, что будет вызвана 1-я реализация method, но я получил это сообщение напечатанным

method(Object o, Integer i)

Я прочитал из specs , что методы с переменными аргументами (varargs) не рассматриваются в phase 1 , но этот компилятор для меня не интуитивен.

Ответы [ 6 ]

0 голосов
/ 22 апреля 2019

Определение метода Сигнатура основана на трех фазах: первые две фазы основаны на сопоставлении не-args метода, а в 3-й фазе рассматриваются методы с var-args.

Метод с non-var-args будет иметь больший приоритет по сравнению с методом с var-args, если оба метода кажутся вызванными

 // least priority method if both method arguments matching with the calling one
 public void method(String s, Integer i, Object... o) {
    System.out.println("method(String s, Integer i, Object... o)");
  }

  public void method(Object o, Integer i) {
    System.out.println("method(Object o, Integer i)");
  }

Вот технические характеристики:

Шаг 2 времени компиляции: определение сигнатуры метода

  1. На первом этапе выполняется разрешение перегрузки без разрешения преобразования или распаковки или использования вызова метода переменной арности . Если на этом этапе не найдено подходящего метода, обработка продолжается до второго этапа.
  2. На втором этапе выполняется разрешение перегрузки, в то время как разрешает упаковывать и распаковывать , но все же исключает использование вызова метода переменной арности . Если на этом этапе не найдено подходящего метода, обработка продолжается до третьего этапа.
  3. Третья фаза позволяет комбинировать перегрузку с методами переменной арности , упаковкой и распаковкой.

Согласно правилу 3-й фазы: перегрузку разрешено комбинировать с var-args, т.е. метод с var-args будет иметь меньший приоритет

0 голосов
/ 22 апреля 2019

Как объяснено в Шаг 2 времени компиляции: определение сигнатуры метода :

На первом этапе (§15.12.2.2) выполняется разрешение перегрузки без разрешения преобразования в бокс или распаковку,или использование переменной метода вызова арности.Если на этом этапе не найдено подходящего метода, то обработка продолжается на втором этапе.

На втором этапе (§15.12.2.3) выполняется разрешение перегрузки, в то же время разрешается упаковка и распаковка, но все же исключается использование метода переменной арности.призывание.Если во время этой фазы не найдено подходящего метода, тогда обработка продолжается до третьей фазы.

Третья фаза (§15.12.2.4) позволяет сочетать перегрузку с методами переменной арности, упаковкой и распаковкой.

Таким образом, на первом этапе будет выбран ваш метод без переменных, поскольку он будет строго согласованным .

0 голосов
/ 22 апреля 2019

Вы передаете два параметра, поэтому 2-й метод будет рассмотрен компилятором, который имеет 2 аргумента, поскольку число параметров совпадает с 2-м методом, затем проверка компилятором для типов данных параметров.Но первым ожидаемым параметром для второго метода является «Объект», и вы передаете «Строка».

0 голосов
/ 22 апреля 2019

Если вам нужно вызвать первый метод, используйте вместо этого три параметра, потому что var-args обычно принимают один или любое количество параметров.Таким образом, оператор вызова должен выглядеть следующим образом:

c.method("1", 1,"any argument");

Если вы хотите вызвать первый метод только с двумя параметрами, используйте реализацию следующим образом:

public class C {

    public void method(String s, Object... o) {
        System.out.println("method(String s, Integer i, Object... o)");
    }

    public void method(Object o, Integer i) {
        System.out.println("method(Object o, Integer i)");
    }

}
0 голосов
/ 22 апреля 2019

Сначала вам нужно понять одну из объектно-ориентированных концепций (и ее синтаксис Java) - ООП, полиморфизм и перегрузку. В любом случае, позвонив по номеру

c.method("1", 1);

вы на самом деле вызываете второй метод, который принимает 2 параметра, а не первый, который, кажется, имеет 3 или более параметров. программа на самом деле делает то, что должна.

0 голосов
/ 22 апреля 2019

Это потому, что вы отправили только два аргумента, поэтому будет выполнен метод с двумя параметрами, отправьте три, а метод с тремя параметрами будет выполнен.

...