Методы Java
Объявление
Метод задаёт именованную операцию класса:
public static BigDecimal calculateTotal(
List<BigDecimal> prices,
BigDecimal discount
) throws IllegalArgumentException {
// тело
}В объявлении могут быть:
- аннотации;
- модификаторы доступа и
static,final,abstract,synchronized; - параметры типа;
- возвращаемый тип или
void; - имя;
- список параметров;
throws;- тело либо
;у абстрактного метода.
Сигнатура метода в Java — имя и типы параметров. Возвращаемый тип, имена параметров и throws в сигнатуру не входят, поэтому нельзя объявить два метода, отличающихся только результатом.
Возвращаемое значение
return завершает текущий вызов и при необходимости возвращает значение:
Optional<User> findActive(List<User> users, long id) {
for (User user : users) {
if (user.id() == id && user.active()) {
return Optional.of(user);
}
}
return Optional.empty();
}У void-метода допустим return; для раннего выхода. Код после безусловного return недостижим и не компилируется.
Передача аргументов
Java всегда передаёт аргументы по значению.
- Для примитива копируется само число/boolean/char.
- Для объекта копируется значение ссылки.
void rename(User user) {
user.setName("new"); // меняет общий объект
user = new User("other"); // меняет только локальную копию ссылки
}Метод не может переassignить переменную вызывающего кода, но может изменить доступный через ссылку mutable-объект.
Методы экземпляра и static
Метод экземпляра вызывается относительно объекта и имеет неявную ссылку this. static принадлежит классу и не может напрямую обращаться к нестатическим полям без конкретного объекта.
final class Temperature {
private final double celsius;
double celsius() {
return celsius;
}
static Temperature ofCelsius(double value) {
return new Temperature(value);
}
}Статическая фабрика может иметь имя, вернуть кэшированный объект или подтип; конструктор всегда создаёт экземпляр объявленного класса.
Varargs
int sum(int... values) {
return Arrays.stream(values).sum();
}Внутри values — обычный массив. Varargs должен быть последним параметром. Вызов обычно создаёт массив, а передача null неоднозначна и опасна. Не стоит использовать varargs на горячем пути без оценки аллокаций.
Контракт метода
Полезно явно понимать:
- допустимые входные значения;
- возвращаемый результат;
- возможные исключения;
- побочные эффекты;
- требования к потокобезопасности и транзакции;
- сложность.
/**
* Возвращает долю в диапазоне [0, 1].
* @throws IllegalArgumentException если total <= 0
*/
double ratio(long part, long total) {
if (total <= 0) {
throw new IllegalArgumentException("total must be positive");
}
return (double) part / total;
}Ловушки
- Считать, что объект передаётся «по ссылке», и ожидать переassign переменной вызывающего кода.
- Делать метод одновременно вычислением, записью в БД и отправкой сообщения без явного контракта.
- Возвращать внутреннюю mutable-коллекцию.
- Злоупотреблять
static, скрывая зависимости и состояние. - Делать длинный список boolean-параметров: вызов
configure(true, false, true)ничего не объясняет.
Вопросы на собеседовании
- Что входит в сигнатуру метода Java?
- Передаёт ли Java объекты по ссылке?
- Чем метод экземпляра отличается от static-метода?
- Как varargs представлен внутри метода?
- Можно ли перегрузить метод только возвращаемым типом?
- Что составляет практический контракт метода?
Связанные заметки
Сигнатура и контракт метода · Перегрузка Java · Переопределение Java · Конструкторы Java · Класс Optional · Работа с исключениями в Java