Свои методы
Чему вы научитесь:
- писать свои методы с параметрами и
returnи вызывать их изmain; - объяснять, почему метод не может изменить переменную, которую ему передали;
- предсказывать, какой из одноимённых методов выберет компилятор;
- разбирать рекурсивный метод по стеку вызовов.
Представьте блендер на кухне. Вы кладёте в чашу продукты, нажимаете кнопку и получаете готовый коктейль. Чтобы сделать ещё один, блендер не собирают заново: в чашу кладут другие продукты и снова нажимают кнопку.
В программе роль такого прибора играет метод. Один метод вы пишете в каждой программе — это main. Но в класс можно добавить и свои методы.
Зачем? Если одно вычисление нужно в программе пять раз, без метода его пришлось бы написать пять раз, а найденную в нём ошибку — исправлять в пяти местах.
Метод записывают один раз, а вызывают сколько угодно. Вот метод, который возводит число в квадрат:
public class Main {
static int square(int x) {
return x * x;
}
public static void main(String[] args) {
System.out.println(square(3)); // 9
System.out.println(square(5)); // 25
int total = square(2) + square(4);
System.out.println(total); // 20
}
}Давайте разберём программу по шагам:
- Метод
squareобъявлен внутри классаMain, рядом сmain, а не внутри него. - Программа, как всегда, начинается с
main. Записьsquare(3)— это вызов:mainотдаёт методу число3и ждёт ответа. - Внутри
squareпеременнаяxравна3, иreturn x * x;возвращает9. - На место вызова
square(3)встаёт9, иprintlnпечатает его. - Вызов
square(5)работает так же и даёт25. - В строке
int total = square(2) + square(4);два вызова дают4и16, поэтому вtotalпопадает20.
Заголовок метода
Первая строка метода, static int square(int x), — его заголовок. Он говорит, как вызвать метод и что тот вернёт. Прочитаем его слева направо:
static— как уmain: метод принадлежит самому классуMain, поэтомуmainвызывает его по имени:square(3);int— тип результата: метод вернёт целое число;square— имя метода; его пишут как имя переменной, с маленькой буквы:square,findMax;(int x)— параметр: переменная метода, которая получает значение при вызове.
После заголовка в фигурных скобках идёт тело метода — инструкции, которые выполняются при каждом вызове.
Параметр и аргумент часто путают, а на собеседовании их различают:
- параметр — переменная в заголовке:
xвsquare(int x); - аргумент — значение, которое передают при вызове:
3вsquare(3).
Параметров может быть несколько, через запятую: static int max(int a, int b). Тогда и аргументов при вызове столько же, в том же порядке: max(3, 7).
Порядок методов в классе не важен: square можно написать и ниже main. Метод выполняется не там, где он записан, а тогда, когда его вызывают.
Здесь картинка с блендером неточна. Блендер можно включить и пустым, а метод с параметром без аргумента не вызвать: на square() компилятор ответит method square in class Main cannot be applied to given types.
Инструкция return
Инструкция return делает две вещи:
- отдаёт значение на место вызова;
- сразу завершает метод: строки после неё не выполняются.
Значение после return должно подходить к типу результата: метод с типом int не может вернуть строку "hi".
Компилятор проверяет return строго. Метод с типом результата обязан вернуть значение на любом пути выполнения. Проверка идёт до запуска, поэтому не важно, с какими аргументами метод на самом деле вызывают. Условия компилятор не вычисляет, поэтому у if без завершающего else для него всегда есть путь в обход, даже если ваши условия охватывают все числа.
Методы void
Не каждый метод что-то вычисляет. Иногда он только выполняет действие, например печатает. Тогда вместо типа результата пишут void, как у main:
public class Main {
static void greet(String name) {
System.out.println("Hi, " + name);
}
public static void main(String[] args) {
greet("Anna"); // Hi, Anna
greet("Bob"); // Hi, Bob
}
}Что важно знать о методах void:
returnсо значением в них не пишут, аreturn;без значения завершает метод досрочно;- вызов такого метода стоит отдельной инструкцией:
int n = greet("Anna");не скомпилируется, потому что значения у вызова нет.
Переменные внутри метода
Параметры метода и переменные, объявленные в его теле, — локальные. Они появляются, когда метод вызывают, и исчезают, когда он завершается. Другие методы их не видят:
mainне может прочитатьxизsquare: компилятор ответитcannot find symbol;squareне видит переменныхmain;- поэтому в двух методах можно завести переменные с одним именем, и это будут две разные переменные.
Блендер тоже не знает, что лежит у вас в холодильнике: он работает только с тем, что положили в чашу.
Частая ошибка
Метод возвращает значение не на всех путях:
static int abs(int x) {
if (x < 0) {
return -x;
}
} // ✗error: missing return statementПрограмма не компилируется. Когда x неотрицательный, метод доходит до закрывающей скобки, так и не встретив return. Компилятор проверяет все пути, а не только тот, по которому пойдёт ваш вызов, поэтому ошибка будет, даже если вы вызываете только abs(-5). Допишите return x; перед закрывающей скобкой метода.
Главное
- Метод объявляют в классе рядом с
main:static, тип результата, имя, параметры и тело —static int square(int x) { return x * x; }. - При вызове аргументы попадают в параметры, а
returnотдаёт значение на место вызова и завершает метод. - Метод с типом результата должен вернуть значение на любом пути, иначе программа не скомпилируется:
missing return statement. - Метод
voidничего не возвращает; параметры и переменные метода видны только внутри него.