В Java разрешение перегрузки (overloading) и переопределения (overriding) методов происходит по определённым правилам. При перегрузке (overloading) компилятор выбирает наиболее подходящий метод среди всех версий на этапе компиляции, исходя из типа аргументов в месте вызова.
Важные моменты:
Пример:
class Super { void print(Number n) { System.out.println("Super Number"); } } class Sub extends Super { void print(Integer i) { System.out.println("Sub Integer"); } } ... Sub s = new Sub(); s.print(5); // Sub Integer s.print(5.0); // Super Number
Здесь print(Integer) будет вызван для аргумента типа Integer, а для типа Double — родительский метод.
Если в наследнике переопределён (override) и перегружен (overload) метод, какой из них вызовется при полиморфизме?
Ответ: При полиморфизме всегда выбирается версия метода на основе реального типа объекта для переопределённых методов (overriding). Для перегруженных методов выбор происходит на этапе компиляции на основе типа ссылки.
class A { void test(Number n) { System.out.println("A:Number"); } } class B extends A { void test(Integer n) { System.out.println("B:Integer"); } @Override void test(Number n) { System.out.println("B:Number"); } } ... A obj = new B(); obj.test(1); // Вызовет B:Number, несмотря на то, что существует test(Integer)
История
Разработчик добавил перегруженную версию метода в подкласс, ожидая, что она будет вызвана для всех наследников. В продакшене стало ясно, что вызов через ссылку родительского класса приводит к выбору метода по типу ссылки, а не объекта. В итоге, необходимая логика не выполнялась.
История
В крупном проекте ошибочно перегрузили метод equals(Object) с сигнатурой equals(MyClass obj), думая, что она заменит стандартный equals. При сравнении в коллекциях HashSet работал дефолтный equals(Object), что приводило к несоответствию логики и потерям данных.
История
При добавлении новой версии метода с varargs в иерархию классов, казалось, что для массивов будет вызываться нужная версия. Однако при передаче массива явно, компилятор выбрал не ту перегрузку, в результате чего обработка шла некорректно, а баг долго оставался незамеченным.