Рекурсия в Java
Напишите метод с именем down, который принимает один int с именем n. Если n равен 0 или меньше, остановитесь голым return;. Иначе напечатайте n, затем вызовите down(n - 1) из того же метода. Из main вызовите down(3);. Экран должен показать три строки: 3, потом 2, потом 1. Метод вызывает сам себя с меньшим числом, пока стоп не оборвёт цепочку. Этот самовызов со стопом — то, чему учит эта страница.
Метод, который вызывает сам себя
На странице области видимости mark выполнялся один раз и заканчивался. Здесь down работает, затем запускает другой down с новым аргументом, пока первый вызов ещё не полностью закончен. У каждого вызова свой n. Цепочка кончается только когда вызов натыкается на стоп.
Создайте небольшой файл программы Ladder.java. Строка public class в начале должна совпадать с именем файла: public class Ladder. Не оставляйте старое имя класса Gate или Sign в этом файле; компилятор ждёт совпадения имени класса и имени файла.
Вне main, но всё ещё внутри фигурных скобок класса, напишите static void down(int n). На этой странице оставьте void: каждый шаг печатает, и ничего не нужно возвращать через типизированный return. Стоп использует return; без значения — он лишь завершает этот вызов. Сохраните файл перед компиляцией. Полная первая программа — в следующем блоке.
Ladder.java с down
Это версия, которую вы компилируете первой. В main — один вызов. В down — стоп, печать и самовызов.
public class Ladder {
public static void main(String[] args) {
down(3);
}
static void down(int n) {
if (n <= 0) {
return;
}
System.out.println(n);
down(n - 1);
}
}
Из папки, где лежит Ladder.java, выполните javac Ladder.java. Когда скобки, фигурные скобки и точки с запятой совпадают, javac не пишет своей строки. Затем выполните java Ladder — не java Ladder.java. Уберите окончание .java во второй команде. Те же две команды работают в Windows и macOS. Программа должна напечатать три строки и остановиться: 3, потом 2, потом 1. Она не должна ждать ввода. Если терминал ждёт клавиатуру, в файле ещё остался вызов nextLine из старого упражнения. Удалите его и оставьте down(3); плюс метод down выше.
Пройдите запуск один раз по порядку. Java начинает с main. Вызов down(3) входит с n, равным 3. Это больше 0, поэтому метод печатает 3, затем вызывает down(2). Второй вызов печатает 2, затем вызывает down(1). Третий печатает 1, затем вызывает down(0). Вызов с 0 натыкается на n <= 0 и возвращается без печати. Цепочка кончается. Экран хранит три напечатанные строки.
Каждый из этих вызовов — отдельный проход по тому же тексту метода. У первого прохода ещё есть работа после запуска down(2) — закончить, когда внутренний вызов вернётся. Вы не пишете четыре разных имени метода. Вы пишете один метод и даёте меньшему аргументу нести прогресс к стопу.
Если сменить старт на down(2);, экран должен показать 2 потом 1. Тело метода то же; меняется только первый аргумент, поэтому цепочка короче. Старт с down(4); должен показать четыре строки: 4, 3, 2, 1. Снова тело не меняется; только main выбирает первое значение.
Ставьте стоп первым
Стоп нужно проверять до печати и до самовызова. Если печатать сначала и никогда не проверять n, или всегда вызывать down(n) с тем же значением, программа не закончится. Держите блок if (n <= 0) вверху метода в этой форме для начинающих.
public class Ladder {
public static void main(String[] args) {
down(2);
}
static void down(int n) {
if (n <= 0) {
return;
}
System.out.println(n);
down(n - 1);
}
}
Скомпилируйте и запустите снова: javac Ladder.java, затем java Ladder. Экран показывает 2 потом 1. Стоп по-прежнему обрывает цепочку, когда n достигает 0. Написание down(n) вместо down(n - 1) снова и снова шлёт то же число. Тогда программа может работать, пока система её не остановит. Меньший аргумент — часть идеи: каждый вызов должен двигаться к стопу.
Думайте о стопе как о двери выхода. Печать — работа этого шага. Самовызов — следующий шаг. Без двери каждый шаг открывает другой без конца. Если следующий шаг использует тот же n, вы никогда не идёте к двери. Обе ошибки выглядят по-разному в исходнике, но обе отказываются закончиться чисто на этой форме для начинающих.
Цепочка вызовов рядом с экраном
Прочитайте один стартовый вызов рядом со строками, которые он даёт. Каждая строка — один визит в down, который ещё печатает.
📊 down call chain for down(3)
| Вызов | Значение n | Строка экрана |
|---|---|---|
первый down(3) |
3 |
3 |
затем down(2) |
2 |
2 |
затем down(1) |
1 |
1 |
затем down(0) |
0 |
(нет строки — стоп) |
Частая путаница — оставить стоп. Тогда каждый вызов печатает и вызывает снова бесконечно. Другая путаница — печатать после рекурсивного вызова, а не до него. На этой странице печать идёт первой, поэтому экран считает вниз. Если перенести println ниже down(n - 1), порядок строк меняется — держите печать выше самовызова для обратного счёта здесь.
Область видимости с предыдущей страницы всё ещё чуть важна: n каждого вызова — параметр этого вызова. n внешнего вызова не переписывает себя, когда работает внутренний. У внутреннего отдельный n. Когда внутренний возвращается, внешний продолжает со строки после самовызова — и на этой странице это просто конец метода.
Старое демо Gate с mark(4) может остаться в том же файле и запутать экран, если main всё ещё вызывает mark. Очистите main до down(3); или down(2);, пока учите эту страницу. Не вкладывайте down внутрь фигурных скобок main. Методы сидят внутри класса рядом с main.
Написание System.out.println("down"); в main печатает слово down. Оно не запускает цепочку. Держите down(3);, когда нужны три строки обратного счёта.
Ещё одна форма: стоп ничего не печатает
Вы уже видели, что вызов с 0 возвращается тихо. Можно также потренироваться со стартовым значением 1. Экран должен показать одну строку: 1. Затем следующий вызов — down(0), который останавливается.
public class Ladder {
public static void main(String[] args) {
down(1);
}
static void down(int n) {
if (n <= 0) {
return;
}
System.out.println(n);
down(n - 1);
}
}
После javac Ladder.java и java Ladder экран показывает одну строку: 1. То же тело метода покрывает down(3), down(2) и down(1). Меняется только первый аргумент в main. Этого достаточно для этой страницы для начинающих. Более глубокие идеи вроде возврата суммы из рекурсии ждут следующих курсов; здесь цель — самовызов, меньший аргумент и стоп.
Если экран ничего не показывает, проверьте, не вызывает ли main ещё что-то, или не ошибочен ли тест стопа — например if (n >= 0) остановится до любой печати при старте с положительным n. Держите n <= 0 как тихий выход и положительный старт в main, чтобы появилась хотя бы одна строка.
Перед classes
Вы можете написать down(int n), остановиться, когда n равен 0 или меньше, напечатать n, затем вызвать down(n - 1). Из main один вызов запускает всю цепочку. Экран показывает строки обратного счёта. Метод, который никогда не движется к стопу, не заканчивается. Следующая страница — classes; там вы начинаете строить типы с полями за пределами этих страниц про static-методы.
🧠 Проверьте Свои Знания
Проверьте Свои Знания
Бросьте себе вызов с помощью этой интерактивной викторины и узнайте, насколько хорошо вы понимаете тему
📝 Инструкции
- Внимательно прочитайте каждый вопрос
- Выберите лучший ответ на каждый вопрос
- Вы можете пересдавать тест столько раз, сколько захотите
- Ваш прогресс будет показан вверху