Перейти к содержимому
Теория · Методы · урок 1 из 8

Свои методы

Чему вы научитесь

Чему вы научитесь:

  • писать свои методы с параметрами и return и вызывать их из main;
  • объяснять, почему метод не может изменить переменную, которую ему передали;
  • предсказывать, какой из одноимённых методов выберет компилятор;
  • разбирать рекурсивный метод по стеку вызовов.

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

В программе роль такого прибора играет метод. Один метод вы пишете в каждой программе — это main. Но в класс можно добавить и свои методы.

Зачем? Если одно вычисление нужно в программе пять раз, без метода его пришлось бы написать пять раз, а найденную в нём ошибку — исправлять в пяти местах.

Метод записывают один раз, а вызывают сколько угодно. Вот метод, который возводит число в квадрат:

JAVA
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
    }
}

Давайте разберём программу по шагам:

  1. Метод square объявлен внутри класса Main, рядом с main, а не внутри него.
  2. Программа, как всегда, начинается с main. Запись square(3) — это вызов: main отдаёт методу число 3 и ждёт ответа.
  3. Внутри square переменная x равна 3, и return x * x; возвращает 9.
  4. На место вызова square(3) встаёт 9, и println печатает его.
  5. Вызов square(5) работает так же и даёт 25.
  6. В строке 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 делает две вещи:

  1. отдаёт значение на место вызова;
  2. сразу завершает метод: строки после неё не выполняются.

Значение после return должно подходить к типу результата: метод с типом int не может вернуть строку "hi".

Компилятор проверяет return строго. Метод с типом результата обязан вернуть значение на любом пути выполнения. Проверка идёт до запуска, поэтому не важно, с какими аргументами метод на самом деле вызывают. Условия компилятор не вычисляет, поэтому у if без завершающего else для него всегда есть путь в обход, даже если ваши условия охватывают все числа.

Методы void

Не каждый метод что-то вычисляет. Иногда он только выполняет действие, например печатает. Тогда вместо типа результата пишут void, как у main:

JAVA
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;
  • поэтому в двух методах можно завести переменные с одним именем, и это будут две разные переменные.

Блендер тоже не знает, что лежит у вас в холодильнике: он работает только с тем, что положили в чашу.

Частая ошибка

Метод возвращает значение не на всех путях:

JAVA
static int abs(int x) {
    if (x < 0) {
        return -x;
    }
} // ✗
TEXT
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 ничего не возвращает; параметры и переменные метода видны только внутри него.