Java перегрузка или переопределение

Чем отличается перегрузка от переопределения?

Полиморфизм – соль ООП. Перегрузка (overload) и переопределение (override) – два инструмента достижения полиморфного поведения в Java.

Перегрузкой реализуется ad-hoc-полиморфизм. Это значит «один и тот же» метод может работать с разными параметрами. С технической точки зрения это просто два разных метода, сигнатуры которых имеют одинаковое название, но разный набор параметров. Важно помнить, что для перегрузки не достаточно различий только модификаторов, возвращаемых типов и списков исключений.

Ad-hoc – не совсем настоящий полиморфизм, так как при нём используется раннее, или статическое связывание (early binding, static dispatch). Это значит, что для выбора конкретного варианта метода используется информация о типе переменной, а не объекта в ней лежащего, и происходит это еще при компиляции.

Если в классе объявлены два перегруженных метода, а аргумент в вызове подходит под оба, случится ошибка компиляции. В примере ниже компилятор не может выбрать между вариантами метода println с параметром char[] и со String , так как null может быть и тем и другим.

Переопределение (override) дает полиморфизм подтипов. Это реализация/подмена метода нефинального родительского класса или интерфейса. С помощью этого механизма достигается поведение, когда экземпляр хранится под типом родителя, но реализация методов используется специфичная для этого конкретного подтипа. Пример:

List list = new LinkedList<>();
list.add(“foo“);

Здесь метод add вызывается общий для всех списков, но добавлен будет именно элемент связного списка.

Выбор конкретного метода происходит в последний момент, в процессе работы программы, в зависимости от типа объекта. Это называется позднее или динамическое связывание методов (late binding, dynamic dispatch).

Переопределение имеет непосредственное отношение к принципу подстановки Лисков (LSP): в хорошем объектно-ориентированном коде для вызывающего кода переопределенный метод не должен быть отличим от оригинального.

Читайте также:  Изменить свойство css через javascript

Переопределенный метод принято снабжать аннотацией @Override . Ее отсутствие допускается, но компиляция не перегружающего метода с такой аннотацией приведет к ошибке.

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

Статические методы нельзя переопределить, можно только перегрузить.

О внутренностях процесса связывания можно почитать в этой статье.

Источник

Кофе-брейк #139. Перегрузка и переопределение в Java. 5 методов Java, о которых вы не знали

Java-университет

Кофе-брейк #139. Перегрузка и переопределение в Java. 5 методов Java, о которых вы не знали - 1

Источник: Medium Благодаря этой статье вы узнаете о методах переопределения (Overriding) и перегрузки (Overloading) в языке Java. Из-за того, что оба этих термина часто путают между собой, стоит четко понимать предназначение каждого метода и варианты их применения.

Перегрузка (Overloading)

Использование более одного метода с одним и тем же именем, но с разными параметрами в одном и том же классе или методе между суперклассом и подклассом в Java называется перегрузкой (Overloading). Чтобы этого избежать, используется один метод вместо множества, выполняющих аналогичные действия. Поясним на примере:

 public class MethodOverloading < public static void main(String[] args)< MethodOverloading operation = new MethodOverloading(); operation.mod(12,4); operation.mod(12.4,4.2); >void mod(double a, double b) < System.out.println(a % b); >void mod(int a, int b) < System.out.println(a % b); >> 

В этом коде метод операции перегружен. Методы с одинаковыми именами принимают параметры разных типов. Выбор режима определяется отдельно для параметров int и double . Когда мы запускаем программу, operation.mod (12,4) запускает void.mod (int a, int b) , а operation.mod (12.4,4.2) запускает void.mod (double a, double b) .

Переопределение (Overriding)

В Java мы можем создать суперкласс и подклассы, которые наследуются от этого класса. Эти подклассы могут переопределять и заменять методы родительского класса, которые они наследуют. Это делается с помощью метода переопределения (Overriding). Лучше понять это можно на примере:

 public class MethodOverriding < public static void main(String[] args) < Cat cat = new Cat(); cat.sound(); Bee bee = new Bee(); bee.sound(); >> class Animal < void sound()< System.out.println("Animal sounds"); >> class Cat extends Animal < @Override void sound() < System.out.println("Cat : meow meow"); >> class Bee extends Animal < @Override void sound() < System.out.println("Bee : buzz buzz"); >> 

В этом примере кода создается суперкласс с именем Animal и подклассы с именами Cat и Bee , унаследованные от этого суперкласса. Метод sound в суперклассе переопределен. Примечание: Разделение перегруженных методов происходит на этапе компиляции. Разделение переопределенных методов происходит на этапе выполнения.

Читайте также:  Turn off all error php

5 методов Java, о которых вы не знали

Источник: Javarevisited Экосистема разработки на языке Java имеет много доступных инструментов, которые программисты могут импортировать и использовать в своих программах. В их число входят встроенные классы и методы. Они заметно упрощают работу программисту, позволяют лучше понимать и писать код. О них следует знать каждому разработчику. Тут приведены 5 методов Java, которые встречаются достаточно редко, но могут оказаться очень полезными в работе.

1. decrementExact

decrementExact() — это базовая функция Java из класса Math , которая уменьшает/вычитает заданный аргумент (число) на единицу и возвращает результат. Эта функция противоположна функции incrementExact() . Например, если заданный аргумент равен 11, то результатом будет 10. Если уменьшение аргумента приводит к переполнению его типа данных, создается исключение. Поэтому важно соблюдать осторожность при использовании этой функции, особенно для больших чисел. Обычно для этой функции используются целые числа. Синтаксис:

 System.out.println(Math.decrementExact(11)); // Output: 10 

2. getAsDouble

getAsDouble() является методом, принадлежащим классу OptionalDouble . Объект OptionalDouble — это тот объект, который потенциально может содержать двойное число. Методы в классе можно использовать для работы с двойным значением, присутствующим в объекте, или указать, что двойное значение вообще не содержится. getAsDouble() является одним из таких методов, и он возвращает двойное значение, если оно присутствует. В противном случае появляется исключение NoSuchElementException . Синтаксис:

 OptionalDoubleObject.getAsDouble(); 
 OptionalDouble num = OptionalDouble.of(15.0); System.out.println(num.getAsDouble()); // Output: 15.0 

3. absExact

Метод absExact() аналогичен функции abs() в классе Math . Он возвращает абсолютное значение числа, которое является положительным значением числа независимо от его знака. Разница лишь в том, что он делает это только в том случае, если он точно представлен как его тип данных ( int или long ). Если результат возвращаемого значения превышает исходный тип данных, появляется исключение ArithmeticException . Синтаксис:

 System.out.println(Math.absExact(-11)); // Output: 11 

4. endsWith

endsWith() является встроенным строковым (built-in string) методом, который возвращает логическое значение в зависимости от того, заканчивается ли данная строка определенным суффиксом (конечным словом/строкой) в параметрах. Этот метод противоположен методу startsWith() , с которым наверняка знакомы многие разработчики. Синтаксис:

 String.endsWith(String suffix); 
 String phrase = "I like bananas"; System.out.println(phrase.endsWith("bananas")); // true System.out.println(phrase.endsWith("Tandrew")); // false /* Output: true false */ 

5. divideUnisgned

Метод divideUnsigned() представляет собой метод из класса Integer , который позволяет разделить два числа и вернуть результат деления. Целые числа без знака (Unsigned), по сравнению с обычными целыми числами со знаком (Signed), могут представлять только положительные числа. И целые числа без знака, и целые числа со знаком имеют одинаковое количество чисел в своем диапазоне (размер диапазона составляет 65 536 чисел). Однако поскольку целые числа без знака не могут быть отрицательными, их максимальное значение в положительном диапазоне намного выше, чем максимальное значение для обычного целого числа со знаком. Чтобы упростить это, мы можем вместо этого рассмотреть пример signed и unsigned байта. Байты имеют диапазон 256 чисел. Обычный байт может иметь значение от -128 до 127. Однако байт без знака может иметь значение от 0 до 255. В остальном функция работает точно так же, как обычное деление. Синтаксис:

 Integer.divideUnsigned(int dividend, int divisor); 
 int dividend = 10; int divisor = 5; int quotient = Integer.divideUnsigned(dividend, divisor); System.out.println(quotient); // Output: 2 

Заключение

  • decrementExact — уменьшает/вычитает заданное число на 1
  • getAsDouble — часть функции OptionalDouble , возвращает число с двойным значением или указывает на его отсутствие
  • absExact — возвращает абсолютное значение числа, если оно может быть представлено как исходный тип данных
  • endsWith() — возвращает логическое значение в зависимости от того, существует ли указанный суффикс в данной строке
  • divideUnsigned() — выполняет обычное деление, возвращает результат деления числа
Читайте также:  Java software and solutions

Источник

Оцените статью