JavaRush /Курсы /Модуль 2. Java Core /Перегрузка методов ч.2

Перегрузка методов ч.2

Модуль 2. Java Core
2 уровень , 4 лекция
Открыта

— Привет, Амиго! Пару дней назад я тебе рассказывал о перегрузке методов. Ты все понял?

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

— Отлично! Я вижу, что ты хорошо выучил тот урок. Сегодня я хочу лишь немного расширить твои познания в этом деле. Как ты думаешь, какой метод будет вызван в каждом случае?

Код
class Cat
{
 public static void print(int n)
 {
  System.out.println(n);
 }
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }
 public static void print(String s)
 {
  System.out.println(s);
 } 
public static void main(String[] args)
{
  Cat.print(1);
  Cat.print((byte)1);
  Cat.print("1");
  Cat.print(null);
 }
}

— Затрудняюсь ответить.

— В первом случае 1 имеет тип int, у нас есть 100% совпадение метода, который принимает int. Будет вызван первый void print(int n).

Во втором случае, у нас нет метода, который принимает byte. Но есть два метода, которые принимают short и int. По стандарту расширения типов, byte сначала будет расширен до short, а уж затем расширен до int. Вердикт – будет вызван метод void print(short n).

В третьем случае у нас есть 100% совпадение метода, который принимает String. Будет вызван метод void print(String s).

В четвертом случае у нас неопределенность. null не имеет определенного типа, компилятор откажется компилировать этот код. В таком случае нужно написать Cat.print((Integer)null), чтобы вызвать третий метод и Cat.print((String)null), чтобы вызвать четвертый.

— Очень познавательно, спасибо.

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

Код
class Cat
{
 public static void print(short n)
 {
  System.out.println(n);
 }
 public static void print(Integer n)
 {
  System.out.println(n);
 }

 public static void main(String[] args)
 {
  Cat.print((byte)1);
  Cat.print(1);
 }
}

В первом случает, тип byte будет расширен до short и произойдет вызов первого метода: void print(short n).

Во втором случае неявно будет выполнено разрешенное преобразование от int к Integer, и произойдет вызов второго метода void print(Integer n).

— Неожиданно.

— Нет, неожиданно – это тут:

Код на Java Описание
 class Cat
{
 public static void print(Object o)
 {
  System.out.println(o);
 }
 public static void print(String s)
 {
  System.out.println(s);
 }

 public static void main(String[] args)
 {
  Cat.print(1);
  Cat.print(null);
 }
}
В первом случае int будет расширен до Integer, а так как нет метода для Integer, то вызовется наиболее подходящий метод, т.е. метод void print(Object o)

Во втором случае, ошибки компиляции не будет и вызовется метод void print(String s), что несколько не очевидно.

— Надеюсь, Амиго ты понял, что лучше всего в таких случаях указать оператор преобразования типа, как в случае с (byte), чтобы точно знать, какой метод вызовется.

— Уж от чего, от чего, а от перегрузки методов я никаких проблем не ожидал. И тут – на тебе. Спасибо, Риша, буду держать ухо востро и не расслабляться.

3
Задача
Java Core, 2 уровень, 4 лекция
Недоступна
Выполняем перегрузку!
Как хорошо, что в Java существует переопределение методов! Сколько проблем это решает, какую свободу действий предоставляет! Так что берем его на вооружение, и продолжаем усваивать на практике. В этот раз давайте напишем два метода по имени print. Один будет печатать целые числа, другой — строки.
3
Задача
Java Core, 2 уровень, 4 лекция
Недоступна
Int и Integer
В конце первого квеста вы узнали, что для каждого примитивного класса в Java существует его непримитивный аналог. Скоро эти непримитивные будут везде, помяните моё слово! А пока — напишем два разных метода вывода на экран, один для примитивного типа int, второй — для непримитивного Integer.
3
Задача
Java Core, 2 уровень, 4 лекция
Недоступна
Свобода печати
На JavaRush — свобода печати, невзирая на секретность. Печатайте что угодно, и как угодно. Только создавайте для этого специальные методы, чтобы заодно потренироваться в перегрузке этих самых методов. Итак, напишите полдесятка методов print с разными параметрами. Какими? Включайте фантазию!
3
Задача
Java Core, 2 уровень, 4 лекция
Недоступна
Три метода и минимум
Можем ли мы сравнить два числа разного типа? Человеческие существа, в подавляющем большинстве с этой задачей справляются. А вот роботам — тяжко. Сравнивать double с int для них, как для людей сравнивать тёплое с мягким. Не будем утомлять роботов: создадим 3 перегруженных метода min для long, double и int.
3
Задача
Java Core, 2 уровень, 4 лекция
Недоступна
Три метода и максимум
Мы снова на границе влияния планеты Линейный Хаос, где живут Упорядоченные Изоморфы. Все, кто хотят получить визу, решают задачки на сортировку и упорядочивание. В этот раз они очень добры, задача — весьма проста: вам нужно создать 3 метода, которые возвращают максимум из двух чисел long, double или int.
Комментарии (11)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Руслан Никитин Уровень 109
25 июля 2024
"Прежде всего, JVM разумно ленива: она всегда будет прилагать наименьшие усилия для выполнения метода. Таким образом, когда вы думаете о том, как JVM обрабатывает перегрузку, имейте в виду три важных особенности компилятора: 1. Расширение (widening). 2. Упаковка (autoboxing and unboxing). 3. Аргументы переменной длины (varargs). Обратите внимание, что JVM выполняет их в том порядке, в котором они указаны. Если не найден подходящий метод сначала примитив расширяется: byte -> short -> int -> long -> float -> double. Если не будет найдено не одного метода для расширенного типа, то упаковывается в свой объект обёртку( int - > Integer, short - Short, double - Double и т.д) и начинает искать метод принимающий обёртку. Если не находит и его, то расширяется(уже будучи объектом) до Number, и затем до Object. " habr(c)
25 января 2023

Во втором случае, ошибки компиляции не будет и вызовется метод 
void print(String s), что несколько не очевидно.
Интересно, по какой причине будет вызван void print(String s)
Вячеслав Уровень 108 Expert
2 марта 2023
Т.к. у тебя метод с переданным в него null может примениться только методу с ссылочным типом - String. String "уже" чем Object, поэтому у компилятора не возникает проблемы с вызовом, они на разных уровнях находятся. А в первом примере была ошибка из-за того, что там указано было 2 метода, которые компилятор мог вызвать при передаваемом null: в котором принимается Integer и String. И уже между ними он не понимает, куда передать null - оба они на одном уровне находятся
17 июля 2023
О, спасибо! Я тоже якорь бросил на этом вопросе
Марат Гарипов Уровень 108 Expert
13 июня 2022
Кто бы мог подумать, что подсказки IDEA могут мешать обучению... Увидев, развидеть уже не получается)) Лишают удовольствия от решения задач!
ZloyLis Уровень 58
5 апреля 2022
Мне кажется или задача "Что-то лишнее" - слегка глуповатая. Достаточно прочитать задание до конца, где и прописан ответ.
Pavel Уровень 48
13 апреля 2022
А я искал в чем подвох, не может быть так легко)))
Сергей Уровень 108 Expert
5 апреля 2022
В первом листинге говорится, что print(null) не найдет правильного метода и компилятор выдаст ошибку. В последнем листинге про этот же пример говорится, что будет вызвать метод print(String s). Где правда?
Денис Уровень 108 Expert
6 апреля 2022
Правда в силе.
Stas S Уровень 108 Expert
14 апреля 2022
Если я правильно понял, вся магия в том, что для компилятора Integer == String , как два ссылочных типа переменных и он не знает к какому именно приводить наш null - ошибка "Ambiguous method call. Both" (двусмысленный вызов метода т.е. не явный) В то же время String гораздо "уже", чем Object т.е. ближе к нашему null , грубо говоря сначала приведение сработало бы к String, а потом уже к Object. А раз мы уже привели к String и у нас есть такой метод, нет конфликта с Object и все прекрасно работает.
Владимир Уровень 109 Expert
20 мая 2022
в точку, полезный коммент!