Как Java выбирает перегруженный метод?

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

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

  • в первую очередь выбираются методы, подходящие по типу, в том числе учитываются примитивные и ссылочные типы;
  • если на первом этапе выбрать нужный метод не удалось, то учитывается возможность boxing/ unboxing;
  • если и на втором этапе не нашлось требуемого метода, то поиск продолжается с учётом vararg-параметров.

В случае, если требуемый метод не нашёлся, компиляция завершается с ошибкой.

Если при поиске на определённой фазе, находится сразу несколько пригодных методов, выбирается наиболее специфичный. Из двух методов более специфичным считается тот, у которого типы параметров являются подтипами сравниваемого с ним. Таким образом аргументы метода, определённого как более специфичный, подойдут для другого метода, а наоборот нет.

// Сигнатуры foo в порядке убывания приоритета
void foo(long a, Object b) {} // Фаза 1: только upcasting по обоим параметрам
void foo(Integer a, Object b){} // Фаза2: для первого параметра понадобится боксинг
void foo(int a, Object... b) {} // Фаза 3: vararg
void foo(long a, Object... b) {} // Фаза 3:тоже vararg, но метод менее специфичный - long шире чем int
 
void bar(Integer a, int b) {}
void bar(Integer a, Object b) {}
void baz(Object a, Long b) {}
 
void test () {
  foo((int) 42, "Это будет Object");  // Эти параметры удовлетворяют всем трём       фазам - используется первая.
  bar(1, 2); // Оба метода из фазы 2 (нужен боксинг для первого аргумента), int  не подтип Object.
  bar(l, 2); // int -> Integer -> Object работает, int -> long -> Long не работает.
}
Поделиться уроком

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *