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

Перегрузка методов | часть 2

Java Core
5 уровень , 3 лекция
Открыта

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

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

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

Код
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), чтобы точно знать, какой метод вызовется.

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

Комментарии (293)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Vladislav Terekh Уровень 34
23 ноября 2025
Копипаста для тех кому лень нажать на самые популярные: Для тех кто читает только первые несколько комментариев, а вопрос про String и null появился: "В первом примере он не может скомпилироваться не от того, что null не может взять не один конструктор, а наоборот, его готовы взять сразу два: String и Integer. Поэтому возникает неопределенность на которую указывает компилятор. Во втором примере, null тоже готовы взять двое, но так как String - потомок Object'a, предпочтение отдается String'у. Не будь его, null взял бы себе Object."
Anonymous #3585174 Уровень 33
18 августа 2025
Like
Seka Уровень 19
6 августа 2025
поставьте лайк на этот коммент и вы получите ответ на возникший у вас вопрос касательно null в первом и во втором случае. просто нажмите на "популярные" комментарии. Нужна ачивка)
Trofim Veselov Уровень 30
13 июня 2025
Не копипаста для тех, кто печатает копипасту, чтоб его сообщение было популярным: Для тех кто копирует нижний комментарий по вопросу про String и null, и пока копипаста не опуститься - она собирает собирает лайки, потому что есть те, кому лень нажать на самые популярные и эти самые "те" читают только первые несколько комментариев, а вопрос про String и null появился: Похоже, Ваш план по сбору ачивки работает!
Victor Уровень 5
28 марта 2025
Похоже Риша не раскрыл тему, зато комментарии раскрыли тему полностью.
Henry Creel Уровень 32
22 марта 2025
Копипаста для тех кому лень нажать на самые популярные: Для тех кто читает только первые несколько комментариев, а вопрос про String и null появился: "В первом примере он не может скомпилироваться не от того, что null не может взять не один конструктор, а наоборот, его готовы взять сразу два: String и Integer. Поэтому возникает неопределенность на которую указывает компилятор. Во втором примере, null тоже готовы взять двое, но так как String - потомок Object'a, предпочтение отдается String'у. Не будь его, null взял бы себе Object."
kddima0 Уровень 1
8 марта 2025
Не понял, мы ведь тут делаем даункастинг, а не апкастинг: мы short сужаем до byte, а не наоборот. Почему я не прав, не понимаю. Посните пожалуйста "Во втором случае, у нас нет метода, который принимает byte. Но есть два метода, которые принимают short и int. По стандарту расширения типов, byte сначала будет расширен до short, а уж затем расширен до int". Мы ведь тут приводим short к byte: Cat.print((byte)1);
lom1tr Уровень 44
12 декабря 2024
Копипаста для тех кому лень нажать на самые популярные: Для тех кто читает только первые несколько комментариев, а вопрос про String и null появился: "В первом примере он не может скомпилироваться не от того, что null не может взять не один конструктор, а наоборот, его готовы взять сразу два: String и Integer. Поэтому возникает неопределенность на которую указывает компилятор. Во втором примере, null тоже готовы взять двое, но так как String - потомок Object'a, предпочтение отдается String'у. Не будь его, null взял бы себе Object."
12 декабря 2024
Не буду писать "Копипаста ..." Просто советую прочитать комментарий ниже👇
Evil Rokk17 Уровень 27
3 декабря 2024
Копипаста для тех кому лень нажать на самые популярные: Для тех кто читает только первые несколько комментариев, а вопрос про String и null появился: "В первом примере он не может скомпилироваться не от того, что null не может взять не один конструктор, а наоборот, его готовы взять сразу два: String и Integer. Поэтому возникает неопределенность на которую указывает компилятор. Во втором примере, null тоже готовы взять двое, но так как String - потомок Object'a, предпочтение отдается String'у. Не будь его, null взял бы себе Object."