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

— Від чого, а від перевантаження методів я жодних проблем не очікував. І тут – на тобі. Дякую, Рішо, буду пильним і не розслаблятимуся.

Коментарі (3)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
IronMan57 Рівень 28
24 лютого 2025
Щось я не зрозумів. Яка різниця в самому першому і в самому останньому фрагментах коду, коли в метод print передається значення null? Чому в першому випадку код не скомпілюється, а в останньому буде викликано метод з параметром типу String?
15 квітня 2025
гарне питання, розібрався в ньому. В першому випадку компілятор думає до чого присвої null - до String чи до Integer? Оскільки null підходить і для String, і для Integer, то компілятор не розуміє який метод використати і виникає помилка. В другому ж варіанті компліятор думає між String та Object і між цими типами компілятор явно бачить більш специфічний тип для null - це String. Надіюсь норм пояснив)
IronMan57 Рівень 28
20 квітня 2025
Дякую, все так. Відразу полінувався сам перевірити. З тексту під першим фрагментом коду зрозумів так, що null не приводиться ні до якого іншого типу. Після вашого коментаря перевірив. Виявляється, що навпаки, null, схоже, можна передати замість параметра будь якого не примітивного типу. Наприклад такий код:

class Cat {

    public static void print(String[] array) {
        System.out.println(array);
    }

    public static void main(String[] args) {
        Cat.print(null);
    }
}
також працює. І, в принципі, зрозуміло, чому так - замість посилання ми передаємо null, тобто "пусте" посилання.