Что такое перегрузка метода java

Java Challengers #1: Перегрузка методов в JVM

У нас уже запустился очередной поток курса «Разработчик Java», но у нас ещё осталось немного материалов, которыми бы хотели с вами поделиться.

Добро пожаловать в серию статей Java Challengers! Этот серия статей посвящена особенностям программирования на Java. Их освоение — это ваш путь к становлению высококвалифицированным программистом на Java.

Освоение техник, рассматриваемых в этой серии статей требует некоторых усилий, но они будут иметь большое значение в вашем повседневном опыте в качестве java — разработчика. Избежать ошибок проще когда вы знаете как правильно применять основные техники программирования Java и отслеживать ошибки намного проще, когда вы точно знаете, что происходит в вашем java — коде.

Готовы ли вы приступить к освоению основных концепций программирования на Java? Тогда давайте начнем с нашей первой задачки!

Что такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода java

Термин «Перегрузка методов»

Про термин перегрузка разработчики склонны думать, что речь идет о перезагрузке системы, но это не так. В программировании, перегрузка метода означает использование одинакового имени метода с разными параметрами.

Что такое перегрузка методов?

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

В Листинге 1 показаны методы с разными параметрами, которые различаются количеством, типом и порядком.

Листинг 1. Три варианта перегрузки методов.

Перегрузка методов и примитивные типы

Таблица 1. Примитивные типы в Java

Зачем мне использовать перегрузку методов?

Использование перегрузки делает ваш код чище и проще для чтения, а также помогает избежать ошибок в программе.

Чем перегрузка не является

Помните, что изменение имени переменной не является перегрузкой. Следующий код не скомпилируется:

Вы также не можете перегрузить метод, изменяя возвращаемое значение в сигнатуре метода. Этот код также не скомпилируется:

Перегрузка конструктора

Вы можете перегрузить конструктор таким же способом, как и метод:

Решите задачку по перегрузке методов

Готовы ли вы к первому испытанию? Давайте выясним!

Начните с внимательного изучения следующего кода.

Листинг 2. Сложная задача по перегрузке методов

Хорошо. Вы изучили код. Какой будет вывод?

Правильный ответ приведён в конце статьи.

Что сейчас произошло? Как JVM компилирует перегруженные методы

Для того чтобы понять что произошло в Листинге 2, вам нужно знать несколько вещей о том, как JVM компилирует перегруженные методы.

Прежде всего, JVM разумно ленива: она всегда будет прилагать наименьшие усилия для выполнения метода. Таким образом, когда вы думаете о том, как JVM обрабатывает перегрузку, имейте в виду три важных особенности компилятора:

Если вы никогда не сталкивались с этими техниками, то несколько примеров должны вам помочь их понять. Обратите внимание, что JVM выполняет их в том порядке, в котором они указаны.

Вот пример расширения:

Это порядок расширения примитивных типов:

Что такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода java

(Прим. переводчика — В JLS расширение примитивов описано с большими вариациями, например, long может быть расширен во float или в double.)

Обратите внимание, что происходит за кулисами при компиляции кода:

А вот пример распаковки:

Вот что происходит за кулисами при компиляции этого кода:

И вот пример метода с аргументами переменной длины. Обратите внимание, что методы переменной длины всегда являются последними для выполнения.

Что такое аргументы переменной длины?

Аргументы переменной длины — это просто массив значений, заданный трёмя точками (. ). Мы можем передать сколько угодно чисел int этому методу.

Аргументы переменной длины (varargs) очень удобны тем, что значения могут передаваться непосредственно в метод. Если бы мы использовали массивы, нам пришлось бы создать экземпляр массива со значениями.

Расширение: практический пример

Аналогично, если мы передаём число 1.0 JVM автоматически распознает, что это double.

Распространенные ошибки с перегрузкой

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

Автоупаковка с обёртками (autoboxing with wrappers)

Java — это строго типизированный язык программирования и, когда мы используем автоупаковку с обёртками, есть несколько вещей, которые мы должны учитывать. Во-первых, следующий код не компилируется:

Автоупаковка будет работать только с типом double потому что, когда вы скомпилируете код, он будет эквивалентен этому:

Литералы чисел в коде

Как любопытный факт. Знаете ли вы, что тип char принимает числа?

Что необходимо помнить о перегрузке

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

Это позволяет сохранять код чистым и удобным для чтения, а также снижает риск того, что дублирующие методы сломают часть системы.

Что следует иметь в виду: при перегрузке метода JVM сделает наименьшее усилие из возможных.

Вот порядок самого ленивого пути к исполнению:

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

Ответ

Ответ к Листингу 2 — Вариант 3. efce.

Подробнее о перегрузке методов в Java

Введение в классы и объекты для абсолютных новичков, включая небольшие разделы о методах и перегрузке методов.

Узнайте больше о том, почему важно, что Java является строго типизированным языком и изучите примитивные типы Java.

Изучите ограничения и недостатки перегрузки методов, а также способы их устранения путем использования пользовательских типов и объектов параметров.

Источник

Перегрузка методов в Java

Что такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода javaЧто такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода javaЧто такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода javaЧто такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода javaЧто такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода javaЧто такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода java

Что такое перегрузка метода java. Смотреть фото Что такое перегрузка метода java. Смотреть картинку Что такое перегрузка метода java. Картинка про Что такое перегрузка метода java. Фото Что такое перегрузка метода java

Давайте проведем эксперимент

Представим, что у нас есть такой код, в котором есть два метода с одинаковым названием:

Как Вы видите, тут есть два конструктора (если впервые слышите слово «конструктор», Вам следует почитать статью «Конструкторы в Java»). У них разные параметры, но называются они одинаково. У Вас выдает ошибку?

Почему?
Зачем?

Вот, есть у меня в программе один метод print или один конструктор Dog. Зачем мне еще один?

Дело в том, что перегрузка методов выполняет несколько функций:

Источник

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

— Привет, Амиго! А я расскажу тебе о перегрузке методов.

— Их еще и перегружать можно?! Да что за день сегодня такой!

— С ними много чего можно делать, но не будем об этом.

— Перегрузка – это очень простая операция. На самом деле – это даже не операция над методами, хотя иногда ее называют страшным словом – параметрический полиморфизм.

Дело в том, что все методы внутри класса должны иметь уникальные имена.

— Так вот, это не совсем так. Вернее совсем не так. Метод не должен иметь уникальное имя. Уникальным должно быть объединение из имени и типов параметров этого метода. Их еще называют сигнатурами методов.

КодОписание
Так можно. Два метода имеют уникальные имена.
И так можно. Два метода имеют уникальные имена (сигнатуры).
Все еще уникальные методы.
А так нельзя. Методы не уникальные, хоть и возвращают разные типы.
А так – можно. Параметры методов уникальные.

— Где-то я уже такое видел.

— Ага. Когда ты пишешь System.out.println, Intellij IDEA подсказывает тебе и выдает в подсказке пару десятков методов print с разными параметрами. Компилятор просто определит нужный метод, по типам переменных, которые ты туда передаешь, и пропишет вызов именно его.

— Это, вроде, не сложно. Не полиморфизм, однако.

— Точнее — не переопределение методов

Кстати, обращаю твое внимание, что имена параметров роли не играют – они теряются при компиляции. После компиляции о методе известно только его имя и типы параметров.

Источник

Руководство по методам перегрузки в Java

Перегрузка относится к определению нескольких методов с одинаковыми именами, но разными сигнатурами в одном классе. Мы обсудим синтаксис и лучшие методы при перегрузке.

Вступление

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

Поэтому интересно, когда классы начинают предлагать методы с одинаковыми именами – или, скорее, когда они перегружают методы, следовательно, нарушают стандарты чистого кода, такие как не повторяйтесь (СУХОЙ) принцип.

Тем не менее, как будет показано в этой статье, методы с похожими/одинаковыми именами иногда полезны. Они могут повысить интуитивность вызовов API, а при экономном и разумном использовании они могут даже улучшить читаемость кода.

Что такое перегрузка метода?

Перегрузка – это процесс определения нескольких методов с одинаковыми именами в одном классе.

Важно напомнить себе о том, как объявить метод, чтобы получить точное представление о том, как происходит перегрузка.

Видите ли, Java ожидает, что методы будут содержать до шести частей :

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

Поскольку Java может различать сигнатуры методов, она может позволить себе перегрузку методов.

Давайте определим класс с перегруженным методом:

Вызов метода setDetails() с определенным набором аргументов определит, какой метод будет вызван. Если ни одна подпись не соответствует вашему набору аргументов, произойдет ошибка компилятора.

Зачем нам нужна перегрузка метода?

Перегрузка методов полезна в двух основных сценариях. Когда вам нужен класс, чтобы:

Возьмем, к примеру, Адрес класс ниже:

Значения по умолчанию

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

Таким образом, по сути, перегруженные методы снизили требования, предъявляемые к клиентам. Пользователям не обязательно знать полный адрес, чтобы использовать класс.

Методы также создают стандартный способ представления сведений о классе в удобочитаемой форме. Это особенно удобно, когда вызывается функция toString() класса:

Как видно из приведенных выше выходных данных, вызов toString() всегда будет выдавать значение, которое легко интерпретировать — без нулей.

Альтернативные Типы Аргументов

Таким образом, можно задать Адрес детали, позвонив либо:

Тем не менее, в обоих случаях вызов toString для класса приведет к следующему:

Способ перегрузки по сравнению с СУХИМ принципом

Конечно, перегрузка методов вводит повторения в класс. И это противоречит самой сути того, что представляет собой СУХОЙ принцип.

В то время как 1 позволяет клиенту указать адрес без ограничений по формату, 5 это довольно строго.

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

Таким образом, за счет сухости Адрес оказывается более читабельным, чем когда у него есть сеттеры с разными именами.

Перегрузка методов в Java 8+

Тем не менее, нам необходимо отслеживать добавление и удаление адресов. Таким образом, в клиентском классе мы могли бы добавить слушателя, объявив:

Тем не менее, если вы сделаете это и скомпилируете, ваш компилятор выдаст ошибку:

В результате нам приходится включать явные объявления в лямбды. Мы должны указать на точный перегруженный метод, о котором мы говорим. Следовательно, рекомендуемый способ добавления таких прослушивателей в Java 8 и выше-это:

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

Лучшие Практики

Возьмем случай, когда разработчик API сделал неправильный выбор типов параметров при перегрузке. Такой подход привел бы пользователей API в замешательство.

Это, в свою очередь, может сделать их код восприимчивым к ошибкам. Кроме того, практика накладывает чрезмерные рабочие нагрузки на JVM. Они напрягаются, чтобы решить точные типы, к которым относятся плохо спроектированные перегрузки методов.

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

Ограничьте использование varargs в перегруженных методах

Программисты тоже сталкиваются с головоломкой – они должны учитывать, например, количество фиксированных переменных, необходимых объекту адреса.

Полное определение объекта адреса может, например, содержать до восьми полей:

Но помните, что varargs также является отличным способом для учета различных параметров. Таким образом, мы могли бы значительно упростить код, включив метод настройки, такой как:

Таким образом, мы позволили бы клиенту класса сделать что-то вроде:

Тем не менее, это создает проблему. Вызывал ли приведенный выше код этот метод:

Или это относилось к:

Короче говоря, как код должен относиться к этим деталям? Например, конкретные поля адреса или общие сведения?

Компилятор не будет жаловаться. Он не выберет переменную arity метод. Вместо этого происходит то, что разработчик API создает двусмысленность, и это ошибка, ожидающая своего появления. Такие, как это:

Приведенный выше вызов передает пустой массив строк ( новая строка[]<> ). Хотя это не является технически ошибочным, это не решает никакой части проблемы домена. Таким образом, через varargs код теперь стал подвержен ошибкам.

Однако существует способ борьбы с этой проблемой. Это включает в себя создание метода из метода с наибольшим количеством параметров.

В этом случае, используя метод:

Тем не менее, описанный выше подход неэлегантен. Благодаря безошибочности это только увеличивает многословие API.

Будьте в курсе автобоксов и расширения

Если мы вызовем метод:

Мы получим результат:

setNumber(длинный) является вторым выбором компилятора. В отсутствие метода с примитивом int JVM отказывается от автобокса для расширения. Помните, Oracle определяет автобокс как:

…автоматическое преобразование, которое компилятор Java выполняет между примитивными типами и соответствующими им классами-оболочками объектов.

С удалением setNumber(целое число) класс печатает:

Вывод

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

Тем не менее, перегрузка-сложная тактика, которой нужно овладеть. Хотя это выглядит как что — то тривиальное в использовании- это совсем не так. Это заставляет программистов учитывать иерархию типов параметров, например, вводить средства автоматического размещения и расширения Java, и перегрузка методов становится сложной средой для работы.

Кроме того, Java 8 ввела в язык новые функции, которые усугубили перегрузки методов. Например, использование функциональных интерфейсов в перегруженных методах снижает читабельность API.

Они заставляют пользователей объявлять типы параметров в клиентском методе. Таким образом, это сводит на нет всю цель перегрузки метода — простоту и интуитивность.

Источник

Перегрузка и переопределение методов в Java

Изучите основы перегрузки и переопределения методов в Java.

1. Обзор

Перегрузка и переопределение методов являются ключевыми понятиями языка программирования Java, и как таковые они заслуживают углубленного изучения.

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

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

Перегрузка методов-это мощный механизм, который позволяет нам определять API-интерфейсы связного класса. Чтобы лучше понять, почему перегрузка методов является такой ценной функцией, давайте рассмотрим простой пример.

Предположим, что мы написали наивный служебный класс, который реализует различные методы умножения двух чисел, трех чисел и так далее.

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

2.1. Различное количество аргументов

2.2. Аргументы различных типов

Кроме того, правомерно определить класс Multiplier с обоими типами перегрузки методов:

Чтобы понять, почему – давайте рассмотрим следующий пример:

В этом случае код просто не будет компилироваться из – за неоднозначности вызова метода – компилятор не будет знать, какую реализацию multiply() вызывать.

2.3. Тип Продвижения

Проще говоря, один данный тип неявно повышается до другого, когда нет соответствия между типами аргументов, переданных перегруженному методу, и конкретной реализацией метода.

Чтобы более четко понять, как работает продвижение типов, рассмотрим следующие реализации метода multiply() :

Давайте посмотрим быстрый модульный тест, чтобы продемонстрировать продвижение типа:

И наоборот, если мы вызываем метод с соответствующей реализацией, продвижение типа просто не происходит:

Вот краткое описание правил продвижения типов, которые применяются для перегрузки методов:

2.4. Статическая привязка

Возможность связать конкретный вызов метода с телом метода называется связыванием.

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

Компилятор может эффективно установить привязку во время компиляции, просто проверив сигнатуры методов.

3. Переопределение метода

Переопределение методов позволяет нам предоставлять детальные реализации в подклассах для методов, определенных в базовом классе.

Теперь давайте посмотрим, как использовать переопределение метода, создав простое отношение на основе наследования (“is-a”).

А вот надуманный подкласс:

Здесь ясно видно, что если приложение использует экземпляры класса Vehicle , то оно также может работать с экземплярами Car , поскольку обе реализации метода accelerate () имеют одинаковую сигнатуру и один и тот же тип возвращаемого значения.

Давайте напишем несколько модульных тестов для проверки классов Vehicle и Car :

В нашем случае у нас есть доступ к исходному коду для обоих классов, поэтому мы можем ясно видеть, что вызов метода accelerate() на базовом экземпляре Vehicle и вызов accelerate() на экземпляре Car вернет разные значения для одного и того же аргумента.

Таким образом, следующий тест демонстрирует, что переопределенный метод вызывается для экземпляра Car :

3.1. Взаимозаменяемость Типов

Самая большая проблема с переопределением методов заключается в том, что некоторые конкретные реализации методов в производных классах могут не полностью соответствовать LSP и, следовательно, не сохранять заменяемость типов.

Конечно, допустимо сделать переопределенный метод, чтобы принимать аргументы разных типов и возвращать другой тип, но при полном соблюдении этих правил:

3.2. Динамическая привязка

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

Как следствие, компилятору необходимо проверить тип объекта, чтобы узнать, какой метод следует вызывать.

Поскольку эта проверка происходит во время выполнения, переопределение метода является типичным примером динамической привязки.

4. Заключение

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

Источник

Добавить комментарий

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