Сигнатура и контракт метода
В практическом смысле сигнатура Java-метода включает имя и типы формальных параметров; для generic-методов правила также учитывают параметры типа и erasure. Возвращаемый тип, имена параметров, модификаторы и throws не позволяют объявить вторую перегрузку с той же сигнатурой.
int parse(String value) { return 0; }
// long parse(String text) { return 0; } // конфликт сигнатур
int parse(byte[] value) { return 0; } // допустимая перегрузкаCovariant return разрешён при override:
class Parent {
Number value() { return 1; }
}
class Child extends Parent {
@Override
Integer value() { return 1; }
}Контракт
Контракт шире объявления метода:
- предусловия для аргументов и состояния;
- постусловия результата;
- изменяемое состояние и другие side effects;
- допустимые исключения;
- гарантии thread safety, blocking и идемпотентности;
- поведение для
null, пустых данных и границ.
/**
* Резервирует amount единиц.
* @throws IllegalArgumentException если amount <= 0
* @throws InsufficientStockException если остатка недостаточно
* Не меняет остаток при ошибке.
*/
Reservation reserve(int amount) { ... }throws перечисляет checked exceptions декларации, но это лишь часть контракта. Unchecked exception тоже может быть осознанным условием API.
Ошибки
- считать возвращаемый тип частью сигнатуры перегрузки;
- менять в наследнике допустимые входы так, что клиент базового типа ломается;
- не описывать side effect или повторный вызов;
- обещать «никогда null», а на редком пути вернуть
null.
На собеседовании
Можно ли перегрузить метод только возвращаемым типом? Нет.
Входит ли throws в сигнатуру для перегрузки? Нет.
Что такое контракт кроме Java-декларации? Условия, результат, исключения и наблюдаемые эффекты.
Можно ли сузить возвращаемый тип при override? Да, ковариантно.
Связано: Методы Java, Перегрузка Java, Переопределение Java, Полиморфизм.