Статичная переменная java. Статические методы в Java, перегрузка методов, рекурсия. Что такое static

Сложные таблицы Таблица типа
«объекты- объекты- несколько » ( ООН )

Таблица типа «объекты-объекты-несколько

Общий вид таблиц типа ООН:

В этой таблице головка (верхний заголовок) имеет трехъярусную структуру.

Пример 5

Таблица 2.9

Оценки по информатике и математике учеников 7 класса


В этом примере пары образуются из объектов, относящихся к классам «ученик» и «предмет». Свойствами здесь являются оценки, полученные учениками за разные периоды учебы.

Попробуем эту же информацию представить иначе. Образуем пары из объектов, принадлежащих классам «ученик» и «период обучения». Свойствами будем считать оценки, полученные учениками по предметам.

Таблица 2.10

Оценки по информатике и математике учеников 7 класса


Из этого примера видно, что объекты и свойства могут меняться ролями: то, что было объектом, становится свойством, и наоборот. Один или другой вариант следует выбирать в зависимости от цели составления таблицы. Например, чтобы проследить за успеваемостью ученика в разные периоды времени по одному и тому же предмету, удобнее воспользоваться таблицей 2.9. А общую картину успеваемости за весь период обучения проще понять с помощью таблицы 2.10. В таблице 2.11 приведен фрагмент сводной ведомости успеваемости учащихся, имеющейся в конце классного журнала.

Таблица 2.11

Оценки по информатике и математике учеников 7 класса

Таблица типа «объекты - свойства - объекты» (ОСО )

Пример 6

В таблице 2.12 приведены антропометрические данные учеников 7 класса. Эта таблица относится к типу OОС.

Таблица 2.12 Антропометрические данные учеников 7 класса

Результаты, показанные ребятами в школьной спарта­киаде, приведены в таблице 2.13. Эта таблица относится к типу ООН.

Таблица 2.13 Результаты школьной спартакиады

Объединим информацию, содержащуюся в таблице 2.12 и таблице 2.13. Для этого «нарастим» боковик таблицы 2.12, вставив после него нужные графы из таблицы 2.13. Получим:

Таблица 2.14

Антропометрические данные и спортивные результаты учеников 7 класса


В этой таблице свойства «рост» и «вес» не являются парными, они относятся только к объектам класса «ученик». Свойства «результат» и «баллы» характеризуют пары объектов классов «ученик» и «упражнение».

В отличие от таблиц других типов, таблицы типа ОСО нельзя «повернуть набок», так как одиночные свойства объектов обязательно должны находиться в боковике.

Вопросы и задания

1.Какие преимущества обеспечивают табличные информационные модели по сравнению со словесными описаниями? Приведите пример.

2.Любое ли словесное описание можно заменить табличной информационной моделью? Приведите пример.

3.Приведите примеры табличных информационных моделей, с которыми вы сталкивались на уроках в школе.

4.Приведите примеры табличных информационных моделей, с которыми вы сталкивались в повседневной жизни.

5.Каких правил следует придерживаться при составлении таблиц?

в. Информация каких видов размещается в графах таблицы? Можно ли там размещать графические изображения? Приведите пример.

Коротко о главном

Для описания ряда объектов, обладающих одинаковыми наборами свойств, наиболее часто используются таблицы, состоящие из столбцов и строк. Представленная в таблице информация наглядна, компактна и легко обозрима.

Таблица типа «объекты-свойства» - это таблица, содержащая информацию о свойствах отдельных объектов, принадлежащих одному классу.

Таблица типа «объекты-объекты-один » - это таблица, содержащая информацию о некотором одном свойстве пар объектов, чаще всего принадлежащих разным классам.

Таблица типа «объекты-объекты-несколько » - это таблица, содержащая информацию о нескольких свойствах пар объектов, принадлежащих разным классам.

Таблица типа «объекты-свойства-объекты» - это таблица, содержащая информацию и о свойствах пар объектов, принадлежащих разным классам, и об одиночных свойствах объектов одного из классов.

Таблица типа «объекты-свойства» — это таблица, содержащая информацию о свойствах отдельных объектов, принадлежащих одному классу.

Общий вид таблиц типа ОС:

Количество строк в таблице зависит от количества имеющихся объектов, а количество столбцов — от количества рассматриваемых свойств.

Пример 1

В этой таблице приведена информация о некоторых древних русских городах, хранящих уникальные памятники нашей культуры и истории и образующих всемирно известное Золотое кольцо России. Эта информация отражена в заголовке таблицы.

В таблице представлены объекты «Владимир», «Кострома», «Переславль-Залесский» и «Гусь- Хрустальный», принадлежащие классу «город». Для каждого объекта приведены значения свойств «год основания», «основатель» и «достопримечательность», выраженные числами и словами.

В маленьких таблицах (из 3-4 строк) объекты можно перечислять в произвольном порядке. Если объектов в таблице много, то располагать их надо в некотором осмысленном порядке, согласно некоторому правилу. Например, в вышепредставленной таблице города могут быть перечислены в алфавитном порядке, по возрастанию или убыванию годов их основания.

Если в таблице типа ОС свойств больше, чем объектов, то ее можно «повернуть набок» — строки превратить в графы, а графы — в строки.

Например:

Что именно располагать в головке, а что в боковике — объекты или свойства, — зависит от конкретной таблицы. Как правило, таблица, в которой много строк и мало граф, бывает удобней, чем таблица, содержащая мало строк, но много граф.

Таблица типа «объекты-объекты-один» (ООО).
Таблица типа «объекты-объекты-один» — это таблица, содержащая информацию о некотором одном свойстве пар объектов, чаще всего принадлежащих разным классам.

Общий вид таблиц типа ООО:

В этой таблице головка (верхний заголовок) имеет сложную (двухъярусную) структуру.

Пример 2

Таблица типа ООО может быть «повернута на бок» строки превращены в графы, а графы — в строки.

Например:

В таблице типа ООО фиксируется одно свойство пары объектов, поэтому в ее ячейках всегда содержатся значения одного типа: или числа, или слова, или графические изображения.

Пример 3
В таблице «Расстояния между городами» представлены расстояния между парами объектов, принадлежащих одному классу «город», поэтому объекты этого класса занесены и в головку, и в боковик таблицы. В результате головка таблицы «теряет» один уровень, и сама таблица выглядит проще. Эта таблица также относится к типу ООО.

Подобные таблицы есть в атласах автомобильных дорог. Правда, там они оформляются так:

Пример 4

По этой таблице можно получить представление о том, чем увлекаются ученики 7 класса, какие кружки и секции они посещают. Если ученик увлекается танцами, спортом или компьютерной графикой (посещает соответствующий кружок или секцию), то в нужную ячейку ставится 1, а если нет — 0.

Ячейки этой таблицы содержат числа, но только 0 и 1. Такие таблицы называют двоичными таблицами.

Важная особенность этой таблицы состоит в том, что в ней фиксируются не количественные (сколько?), а качественные свойства (наличие/отсутствие связи между
объектами).

Коротко о главном:

  • Таблица типа «объекты-свойства» — это таблица, содержащая информацию о свойствах отдельных объектов, принадлежащих одному классу.
  • Таблица типа «объекты-объекты-один» — это таблица, содержащая информацию о некотором одном свойстве пар объектов, чаще всего принадлежащих разным классам.

Вопросы и задания:

Последнее обновление: 19.04.2018

Кроме обычных методов и полей класс может иметь статические поля, методы, константы и инициализаторы. Например, главный класс программы имеет метод main, который является статическим:

Public static void main(String args) { }

Для объявления статических переменных, констант, методов и инициализаторов перед их объявлением указывается ключевое слово static .

Статические поля

При создании объектов класса для каждого объекта создается своя копия нестатических обычных полей. А статические поля являются общими для всего класса. Поэому они могут использоваться без создания объектов класса.

Например, создадим статическую переменную:

Public class Program{ public static void main(String args) { Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 1 bob.displayId(); // Id = 2 System.out.println(Person.counter); // 3 // изменяем Person.counter Person.counter = 8; Person sam = new Person(); sam.displayId(); // Id = 8 } } class Person{ private int id; static int counter=1; Person(){ id = counter++; } public void displayId(){ System.out.printf("Id: %d \n", id); } }

Класс Person содержит статическую переменную counter, которая увеличивается в конструкторе и ее значение присваивается переменной id. То есть при создании каждого нового объекта Person эта переменная будет увеличиваться, поэтому у каждого нового объекта Person значение поля id будет на 1 больше чем у предыдущего.

Так как переменная counter статическая, то мы можем обратиться к ней в программе по имени класса:

System.out.println(Person.counter); // получаем значение Person.counter = 8; // изменяем значение

Консольный вывод программы:

Id = 1 Id = 2 3 Id = 8

Статические константы

Также статическими бывают константы, которые являются общими для всего класса.

Public class Program{ public static void main(String args) { double radius = 60; System.out.printf("Radisu: %f \n", radius); // 60 System.out.printf("Area: %f \n", Math.PI * radius); // 188,4 } } class Math{ public static final double PI = 3.14; }

Стоит отметить, что на протяжении всех предыдущих тем уже активно использовались статические константы. В частности, в выражении:

System.out.println("hello");

out как раз представляет статическую константу класса System. Поэтому обращение к ней идет без создания объекта класса System.

Статические инициализаторы

Статические инициализаторы предназначены для инициализации статических переменных, либо для выполнения таких действий, которые выполняются при создании самого первого объекта. Например, определим статический инициализатор:

Public class Program{ public static void main(String args) { Person tom = new Person(); Person bob = new Person(); tom.displayId(); // Id = 105 bob.displayId(); // Id = 106 } } class Person{ private int id; static int counter; static{ counter = 105; System.out.println("Static initializer"); } Person(){ id=counter++; System.out.println("Constructor"); } public void displayId(){ System.out.printf("Id: %d \n", id); } }

Статический инициализатор определяется как обычный, только перед ним ставится ключевое слово static . В данном случае в статическом инициализаторе мы устанавливаем начальное значение статического поля counter и выводим на консоль сообщение.

В самой программе создаются два объекта класса Person. Поэтому консольный вывод будет выглядеть следующим образом:

Static initializer Constructor Constructor Id: 105 Id: 106

Стоит учитывать, что вызов статического инициализатора производится только перед созданием самого первого объекта класса.

Статические методы

Статические методы также относятся ко всему классу в целом. Например, в примере выше статическая переменная counter была доступна извне, и мы могли изменить ее значение вне класса Person. Сделаем ее недоступной для изменения извне, но доступной для чтения. Для этого используем статический метод:

Public class Program{ public static void main(String args) { Person.displayCounter(); // Counter: 1 Person tom = new Person(); Person bob = new Person(); Person.displayCounter(); // Counter: 3 } } class Person{ private int id; private static int counter = 1; Person(){ id = counter++; } // статический метод public static void displayCounter(){ System.out.printf("Counter: %d \n", counter); } public void displayId(){ System.out.printf("Id: %d \n", id); } }

Теперь статическая переменная недоступна извне, она приватная. А ее значение выводится с помощью статического метода displayCounter. Для обращения к статическому методу используется имя класса: Person.displayCounter() .

При использовании статических методов надо учитывать ограничения: в статических методах мы можем вызывать только другие статические методы и использовать только статические переменные.

Вообще методы определяются как статические, когда методы не затрагиют состояние объекта, то есть его нестатические поля и константы, и для вызова метода нет смысла создавать экземпляр класса. Например:

Public class Program{ public static void main(String args) { System.out.println(Operation.sum(45, 23)); // 68 System.out.println(Operation.subtract(45, 23)); // 22 System.out.println(Operation.multiply(4, 23)); // 92 } } class Operation{ static int sum(int x, int y){ return x + y; } static int subtract(int x, int y){ return x - y; } static int multiply(int x, int y){ return x * y; } }

В данном случае для методов sum, subtract, multiply не имеет значения, какой именно экземпляр класса Operation используется. Эти методы работают только с параметрами, не затрагивая состояние класса. Поэтому их можно определить как статические.

Статическим методом называется фрагмент программы, которому присвоено некоторое уникальное имя, и который по этому имени можно вызывать из остальных частей программы. В момент, когда происходит вызов, выполняются действия, перечисленные внутри метода (в его описании или теле).
В объектно-ориентированном программировании основная задача методов заключается в том, чтобы изменять текущее состояние объекта, но до тех пор, когда в программе объекты ещё не используются, методы уже могут вводиться. Метод, который описан внутри некоторого класса, но вызывается без приложения к конкретному объекту этого класса, называется статическим.

Кроме имени и описания, о которых сказано выше, у метода есть ряд других характеристик:

  1. Набор модификаторов.
  2. Тип возвращаемого значения.
  3. Набор аргументов (параметров).

Модификаторы метода

Для того чтобы создать статический метод, перед его именем надо указать модификатор static. Если этого не сделать, то метод можно будет вызывать только в приложении к конкретному объекту данного класса (будет нестатическим).

Модификатор public отвечает за уровень доступа к описываемому методу. Вместо public могут указываться уровни доступа private или protect, а также может не указываться ничего, тогда будет действовать уровень доступа по умолчанию.

С уровнями доступа мы познакомимся подробнее, когда будем создавать свои классы, а пока отметим, что доступ по умолчанию разрешает обращаться к методу из любой части того пакета, в котором метод описан. А уровень public открывает доступ к методу откуда угодно. В том числе и из других пакетов и программ.

Метод main обязан иметь уровень доступа public как раз потому, что к нему обращается виртуальная машина Java, не являющаяся частью какого-либо пакета.

Кроме этого, существуют другие модификаторы, которые, например, позволяют регулировать работу методов в процессе параллельных (многопоточных) вычислений.

Тип возвращаемого значения

Методы в Java условно можно разделить на 2 группы: функции и процедуры. К первой группе относятся методы, очень похожие на функции в математическом смысле. В результате своей работы такие методы возвращают в то место программы, из которого они были вызваны, некоторый конкретный результат существующего типа, то есть это может быть целое или вещественное число или логическое значение (int, double, boolean), массив (ссылка на него), объект (ссылка на него). Возвращаемое значение должно присваиваться переменной подходящего типа или же передаваться какому-либо другому методу в роли аргумента.

В отличие от функций, методы процедурного типа производят какие-либо полезные действия, но не дают законченного результата, который мог бы выражаться в одном конкретном значении или объекте.

Double r = Math.random(); /* random относится к функциям */ System.out.println(r); /* println относится к процедурам */

Если бы мы создали метод, который так же, как и println, печатал бы текст на экран, но при этом подсчитывал бы количество пробелов в тексте, и возвращал бы этот результат, то получили бы функцию. При этом функция продолжала бы выполнять полезные действия, характерные для процедуры println. Соответственно, функция более универсальна, чем процедура, но не всегда необходима.

При создании метода в первую очередь надо определить, будет ли он функцией или процедурой. Для промежуточных вычислений, как правило, используются функции. Для сокращения однотипных фрагментов кода могут подходить и процедуры.

После модификаторов, но также слева от имени метода, указывается тип возвращаемого им значения (если метод является функцией, например: int или double) или же слово void (если метод является процедурой).

Если метод является функцией, то в нём обязательно должна встречаться команда return после которой через пробел указывается то выражение, значение которого должно быть возвращено в качестве результата работы метода.

Все команды, указанные в описании метода после return, выполняться уже не будут, return без аргумента можно использовать внутри процедур. Он будет просто досрочно завершать процедуру (аналог break для цикла).

Аргументы (параметры)

При вызове метода в него из основной программы может передаваться набор некоторых значений. Для того чтобы научить метод их принимать (и внутри метода их обрабатывать), в круглых скобках после имени метода должны быть перечислены пары вида: тип_аргумента имя_аргумента через запятую.

Тогда при вызове метода можно будет указать набор значений, соответствующих по типам, описанным аргументам.

Значение, которые передаются методу в момент вызова, называются фактическими параметрами, а имена аргументов, которые фигурируют в описании метода — формальными параметрами.

Каждый формальный параметр является внутри метода локальной переменной, то есть он недоступен за пределами метода (вне блока его описания). В момент вызова метода фактическое значение копируется в формальный параметр.

В частности, это означает, что, передавая какую-либо переменную базового типа как параметр методу при его вызове, мы не сможем изменить значение этой переменной в основной программе. Если в метод через аргумент передаётся какого-либо объекта или массива, то внутрь метода копируется только ссылка на объект или массив (т. е. их адрес в памяти). Действия, которые мы совершим с массивом или объектом внутри метода, отразятся на состоянии этого массива или объекта в основной программе даже после того, как метод завершит свою работу. Внутри метода мы обращались по тому же адресу и работали с теми же данными в памяти, что доступны в основной программе.

Если имя фактического параметра совпадает с именем формального параметра, то это не влечёт никакой проблемы: внутри метода имеется локальная переменная, в которую при вызове копируется значение одноимённой глобальной переменной. Обращаясь по этому имени внутри метода, будем попадать на локальную переменную и никак не сможем добраться до глобальной.

Описание метода

Метод должен описываться внутри класса, но при этом один метод не описывают внутри другого, то есть метод должен вкладываться непосредственно в блок класса.

Общая схема описания метода:

Модификаторы тип_возвращаемого_значения имя_метода (формальные аргументы) { // действия, выполняемые методом // возможно, return }

Имя метода по традиции должно начинаться с маленькой буквы. Если оно состоит из нескольких слов, каждое следующее слово начинают с заглавной буквы. Имя для метода выбирают так, чтобы было понятно, что он делает.

Рассмотрим несколько примеров:

Public static double kvadk (double) { double t; t = Math.pow(a, 0.5); return t; }

Теперь внутри метода main мы сможем использовать наш метод. Например, так:

Int a = 25; System.out.println(kvadk(a)); // 5.0 System.out.println(a) // 25

При передаче фактических параметров в метод действует автоприведение. Если аргумент фактический не соответствует типу формального, то Java пробует привести фактический аргумент к более универсальному типу (в данном случае int был приведён к double).

Перегрузка методов

Сигнатурой метода называется совокупность его имени и набора формальных параметров.
Java позволяет создавать несколько методов с одинаковыми именами, но разными сигнатурами. Создание метода с тем же именем, но с другим набором параметров называется перегрузкой. Какой из перегруженных методов должен выполняться при вызове, Java определяет на основе фактических параметров.

Void pr(double a) { System.out.println(a); } void pr (String a) { System.out.println(a); } void pr(int a) { for (int i=0; i

Пример использования метода.

Int a = 5; int m = {1, 2, 8, 3} String s = "Мир"; pr (a) //работает исходный метод pr (a+s); // 5 мир, работает первая перегрузка pr (m); // 1 2 8 3 pr (m+a); // ошибка

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

Перегрузка методов реализует такое важное свойство в программировании, как полиморфизм. Полиморфным называется программный код, который связан с одним общим именем, но имеет разные реализации. Какая из реализаций будет работать, выбирается на основе контекста, в котором имя было упомянуто. Конкретно для методов полиморфными являются их перегрузки, а выбор исполняемой перегрузки происходит по параметрам.

Полиморфизм: одно имя, много форм.

Примеры использования методов

Следующая программа ищет и выводит на экран все простые нетривиальные делители числа, введённого пользователем с клавиатуры, начиная с наибольшего из делителей, либо сообщает, что введённое число — является простым.

Import java.util.Scanner; public class Main { public static boolean isPrime(int n) { for(int i = 2; i <= Math.sqrt(n) ; i++) { if(n%i == 0) { return false; } } return true; } public static void main(String args) { Scanner sc = new Scanner(System.in); System.out.print("Введите натуральное число: "); if(sc.hasNextInt()) { int u = sc.nextInt(); if(u > 0) { if(isPrime(u)) { System.out.println("Вы ввели простое число"); } else { System.out.print("Простые делители числа: "); for(int i = (int)Math.sqrt(u); i >= 2 ; i--) { if(u%i == 0 && isPrime(i)) { System.out.print(i+" "); } } System.out.println(); } } else { System.out.println("Вы ввели не положительное число"); } } else { System.out.println("Вы ввели не целое число"); } } }

В следующем примере за счёт перегрузки будет создано несколько одноимённых методов.

Первый вариант метода будет просто переводить строку, т. е. фактически являться боле коротким синонимом встроенного метода System.out.println(). Параметров у этого варианта не будет.

Второй вариант метода (его первая перегрузка), проверяет, есть ли у числового аргумента дробная часть, если её нет, то аргумент приводится к целым и выводится на экран без нулевой дробной части (3 вместо 3.0). В этот метод смогут в качестве единственного аргумента передаваться не только переменные типа double, но и переменные любого другого типа, для которого возможно автоприведение к double (например, любые целочисленные переменные).

Третий метод с одним параметром просто вызывает четвёртый метод, передавая в качестве параметров ему полученный массив, а также пробел в качестве второго параметра. Обратите внимание, что мы вызываем метод, который будет описан далее по ходу программу, это вполне допустимо.

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

Public class Main { public static void pr() { System.out.println(); } public static void pr(double d) { if((int)d == d) { System.out.print((int)d); } else { System.out.print(d); } } public static void pr(double m) { pr(m, " "); } public static void pr(double m, String s) { for(int i = 0; i < m.length; i++) { pr(m[i]); System.out.print(s); } } public static void main(String args) { double arrn = {1, 2.71, 3.14, 15, -5, 92, 0.5}; double p = 3.0; int k = 13; pr(p); // вывод числа, без дробной части при возможности pr(); // переводит строку pr(arrn); // вывод числового массива в строку pr(); // переводит строку pr(arrn,", "); // вывод числового массива в строку через запятую pr(); // переводит строку pr(k); // вывод целого числа через автоприведение } }

В результате работы программы на экран будет выведено:

3 1 2.71 3.14 15 -5 92 0.5 1, 2.71, 3.14, 15, -5, 92, 0.5, 1

Задачи

  1. Создать статический метод, который будет иметь два целочисленных параметра a и b, и в качестве своего значения возвращать случайное целое число из отрезка . C помощью данного метода заполнить массив из 20 целых чисел и вывести его на экран.
  2. Создать метод, который будет выводить указанный массив на экран в строку. С помощью созданного метода и метода из предыдущей задачи заполнить 5 массивов из 10 элементов каждый случайными числами и вывести все 5 массивов на экран, каждый на отдельной строке.
  3. Создать метод, который будет сортировать указанный массив по возрастанию любым известным вам способом.
  4. В массиве хранится 7 явно заданных текстовых строк. Создать программу, которая отсортирует и выведет на экран строки в алфавитном порядке. Например, если были даны такие строки:
Пушкин Лермонтов Некрасов Толстой Л. Н. Толстой А. Н. Есенин Паустовский

Программа должна вывести на экран:

Есенин Лермонтов Некрасов Паустовский Пушкин Толстой А. Н. Толстой Л. Н.

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

Рекурсия

Рекурсией называется метод (функция), которая внутри своего тела вызывает сама себя.

Рассмотрим пример — вычисление факториала. Для того чтобы вычислить n!, достаточно знать и перемножить между собой (n-1)! и n.

Создадим метод, реализующий описанный способ.

Static int fact (int n) { if (n==1) { return 1; } else if (n==2) { return 2; } else { return fact(n-1) * n; } }

Указанный метод вычисляет факториал натурального числа.

Рассмотрим пример, вычисляющий через рекурсию n-ое число Фибоначчи.

Напомним, как выглядят первые элементы этого ряда: 1 1 2 3 5 8 13 …

Static int fib (int n) { if (n==1 || n == 2) { return 1; } return fib (n-2) + fib (n-1); }

Обратите внимание, что в этом методе второй return не помещён в блок else для первого условного оператора. Это допустимо, ведь если выполнится условие и сработает первый return, то произойдёт выход из метода, до второго return исполнение программы дойдёт только в случае невыполнения условия.

Рекурсивные вычисления часто приводят к необходимости повторять одни и те же действия, что существенно замедляет работу программы.

Задачи

  1. Выясните экспериментальном путём, начиная с какого элемента последовательности Фибоначчи, вычисление с использованием рекурсии становится неприемлемым (занимает более минуты по времени).
  2. Создайте гибридный метод, для небольших n вычисляющий n-ое число Фибоначчи с помощью рекурсии, а для значений, превышающих выясненное вами в предыдущей задаче пороговое n, вычисляющий n-ое число Фибоначчи с помощью итерационного алгоритма (цикла, в рамках которого будут сохраняться значения двух предыдущих элементов последовательности).
  3. Подсчитайте, сколько раз потребуется повторно вычислить четвёртый элементы последовательности Фибоначчи для вычисления пятнадцатого элемента.

Стек вызовов

В общем случае в текущий момент времени может исполняться только один единственный метод из всей программы. Это значит, что, если метод а устроен таким образом, что в своём теле он вызывает метод b , а сам а вызывается в main , то при запуске программы управление сначала будет передано методу main , затем методу а , затем методу b . Метод b вернёт результат и управление в а , а вернет результат управления в main , и только потом будут выполняться основные команды, указанные в методе main на остальных строках после вызова a .

Вся иерархия (кто кого вызывал) хранится в специальной области памяти, называемой стеком вызовов. Элементы в этот фрагмент памяти добавляются по следующему принципу: последний добавленный элемент должен быть извлечён первым. Когда работает метод b , получается, что под ним в стеке оказываются метод a и метод main .

В связи с этим в процессе рекурсии существует опасность переполнения стека вызовов.

Существует так называемая сложная рекурсия, при которой метод а вызывает метод b , b вызывает с , а с вызывает а .

2010, Алексей Николаевич Костин. Кафедра ТИДМ математического факультета МПГУ.




Top