Функции в Java —
разбиваем код на блоки
Часто какой-то код в программе нужно повторять много раз в разных местах. Тогда этот код можно поместить в функцию. Функция — это блок кода, у которого есть имя, параметры и возвращаемое значение. Функции можно вызывать по имени в любых местах, в main или в других функциях. Это гораздо удобнее, чем без конца копировать кучу кода, когда вам нужно выполнить его несколько раз.
Функцией называют блок кода, у которого есть имя, параметры и возвращаемое значение. По имени можно вызывать этот блок в любом месте программы.
Параметры — это входные данные, на которые опирается наша функция. Например, функция возводит число в квадрат — ей нужно знать, чему равно в данный момент это число. При одном вызове мы можем указать число и получить его в квадрате, а при другом вызове мы укажем уже другое число, и получим другой квадрат. Так что пока мы пишем код функции, то просто говорим, что нам нужно какое-то дробное число, а какое именно — будет указано в скобках при вызове функции, каждый раз новое.
Многие функции создаются, чтобы посчитать какой-то результат. Этот результат нужно вернуть, то есть передать из кода функции в место, где её вызвали. Например, функция, которая возводит число в квадрат, будет возвращать результат расчета, то есть квадрат числа, которое её дали на вход.
Посмотрим код функции для возведения числа в квадрат. Сначала пишется заголовок функции, где указывается слева направо тип возвращаемого значения, имя функции и в скобках её параметры. Функцию возведения в квадрат часто называют sqr от английского слова square — «квадрат». Поскольку её нужно число, возможно дробное, и возвращает она тоже число, то тип параметра будет double и тип возвращаемого значения тоже будет double .
// Наш заголовок читается так: // статическая, возвращает double, называется sqr, принимает параметром один double static double sqr ( double number) < // Фигурная скобка открывает тело функции - её блок кода. // Чтобы посчитать квадрат числа, нужно его умножить само на себя. // Результат перемножения нужно вернуть из функции словом return вот так: return number*number; >// фигурная скобка закрывает блок функции.
Слово static в заголовке функции пока что будем писать всегда, а разберём подробнее, когда будем делать свои классы.
Фигурные скобки . > обрамляют блок функции. Если закрывающую не поставить, то компилятор решит, что у функции нет конца и так и скажет «missing >«, то есть «отсутствует >«. А если наоборот закрывающих слишком много, то скажет «unbalanced brackets», то есть «скобки не сбалансированы» как про круглые (), так и фигурные <>
Теперь посмотрим на вызов нашей функции, например, в main. Чтобы вызвать функцию нужно написать её имя и в скобках указать значения параметров. Результат работы функции имеет смысл сохранить в какой-нибудь переменной, чтобы потом ей пользоваться, к примеру, чтобы распечатать:
public static void main (String[] args) < // Объявим x равный 10 double x = 10; // Вызвать sqr с параметром x: double result = sqr (x); // Возвращаемое значение sqr подставится прямо сюда // получится double result = 100 System.out.println ("10 в квадрате будет " + result); >
При вызове функции программа выполняет весь её код, вместо параметров подставляя значения, указанные в скобках. Сейчас мы сделали вызов sqr (x) . Значит в параметр подставится число x, а оно сейчас равно 10. В то самое место кода, где мы написали вызов sqr (x)
Тип переменной для хранения результата функции должен соответствовать типу самого результата, поэтому в нашем случае мы сделали double result, а не, например, int, ведь sqr возвращает double.
Теперь на основе функции sqr сделаем в main простой калькулятор — он будет спрашивать у пользователя числа и возводить их в квадрат. Заодно посмотрим, как ещё можно использовать функции.
public static void main (String[] args) < System.out.println ("Это программа для расчета квадратов чисел"); System.out.println ("Введите число:"); // Считаем в x дробное число с клавиатуры Scanner scan = new Scanner (System.in); // Создадим сканер клавиш клавиатуры // Кстати тут мы тоже вызываем функцию - nextDouble, только она уже есть в Java // Мы указываем scan, чтобы подчеркнуть, что вызов именно // для нашего конкретного сканера scan, созданного строчкой выше double x = scan.nextDouble (); // Вызвать sqr с параметром x: double result = sqr (x); // Возвращаемое значение sqr подставится прямо сюда System.out.println (x + " в квадрате будет " + result); System.out.println ("Введите новое число:"); // Мы используем уже введенную раньше переменную x, // поэтому указываем просто x, а не double x: x = scan.nextDouble (); // Снова вызвать sqr с параметром x: result = sqr (x); // Возвращаемое значение sqr подставится прямо сюда System.out.println (x + " в квадрате будет " + result); // Теперь посмотрим другой вариант для той же задачи: System.out.println ("Введите новое число:"); x = scan.nextDouble (); // sqr(x) в программе будет уже просто число, и его можно подставлять куда угодно: System.out.println (x + " в квадрате будет " + sqr (x) ); // И самый короткий вариант: System.out.println ("Введите новое число:"); System.out.println ("В квадрате это будет " + sqr ( scan.nextDouble () ) ); >
В последней строчке мы вызвали сразу nextDouble, sqr и println:
System.out.println («В квадрате это будет » + sqr ( scan.nextDouble () ) );
Компилятор идёт слева направо и видит, что здесь стоит распечатка println. Он пробует её выполнить, но обнаруживает, что строчку для распечатки он получит, только выполнив функцию sqr, а значит, он выполняет сначала её. Но тут снова, чтобы получить число для возведения в квадрат, нужно выполнить scan.nextDouble .
Поэтому прежде всего заработает scan.nextDouble и число будет введено с клавиатуры. Оно будет передано на вход функции sqr и будет возведено в квадрат. Тогда уже оно попадёт в строчку и будет распечатано на экране в функции println.
Получается, что возвращаемое значение одной функции можно сразу дать в качестве входного параметра для другой функции. Это нормально, ведь возвращаем мы число, и на вход нам тоже нужно число. Но при этом, поскольку мы сейчас не заводили никаких переменных, мы уже не сможем использовать результаты работы этой функции где бы то ни было ещё в коде программы. Итак, каскад вызовов делают для краткости кода, но если вы хотите использовать результат где-то ещё в программе, то нужно писать несколько строк и сохранять значения в переменных.
Сейчас в нашем небольшом калькуляторе мы 4 раза подряд совершили один и тот же набор действий — считать число, возвести в квадрат, вывести на экран. Имеет смысл для этих действий завести свою функцию, и таким образом сократить объём кода:
// Для полноты картины приводим нашу функцию sqr static double sqr (double num) < return num*num; >// Назовём функцию ask_and_calc, то есть спросить и посчитать квадрат. // Она ничего не возвращает, поэтому вместо типа возвращаемого значения // пишется void, по-английски пустота. // Данные функция сама возьмёт с клавиатуры и параметры ей не нужны. // Поэтому в круглых скобках ничего нет - это будет функция без параметров. static void ask_and_calc () < System.out.println ("Введите число:"); Scanner scan = new Scanner (System.in); double x = scan.nextDouble (); double result = sqr (x); System.out.println (x + " в квадрате будет " + result); >// Кстати main тоже ничего не возвращает, поэтому он void . // А параметром идёт String[] args, что означает "набор String". // Эти строки можно указывать при запуске приложения из командной строки, // но мы их пока не будем использовать. public static void main (String[] args) < System.out.println ("Это программа для расчета квадратов чисел"); // Больше не копируем один и тот же код 4 раза, а просто вызываем функцию ask_and_calc(); // название читается по-английски, и сразу понятен смысл ask_and_calc(); ask_and_calc(); ask_and_calc(); >
Итак, функция ask_and_calc ничего не возвращает, а значит вместо типа возвращаемого значения пишется void — «пустота». Параметров у этой функции тоже нет, так что пишутся пустые скобки () .
Как сократился main! Он раньше занимал целый экран, а теперь всего несколько строчек. И как понятен он теперь — практически можно читать на английском языке! В этом и состоит удобство использования функций — код разбит на блоки с понятными названиями и их можно вызывать много раз подряд.
О термине «процедура». Строго говоря, функцией называется блок кода, который что-то возвращает. Когда используется слово void, и ничего не возвращается, то говорят, что это процедура. Но разница так тонка, что в обиходе слова «функция» и «процедура» используются практически как синонимы.
О термине «метод». И функции, и процедуры ещё называют методами. Слово метод употребляют, когда хотят подчеркнуть, что функция или процедура принадлежат классу. Классы мы будем изучать позже и тогда вернёмся к вопросу терминологии. В простом понимании функция, процедура и метод — это всё синонимы.
О термине «аргумент». Также параметры ещё называют аргументами. Так что можно сказать «параметр функции», а можно «аргумент функции» и это будет одно и то же.
Наш main можно было бы сократить ещё больше, если бы мы вызывали ask_and_calc в цикле вот так:
public static void main (String[] args) < System.out.println ("Это программа для расчета квадратов чисел"); // спросить число и возвести его в квадрат 4 раза for (int i = 0; i
Когда мы делаем функцию и затем вызываем её в коде много раз или пишем цикл, который вызывает один и тот же код много раз, мы экономим объём программы, и при этом делаем её понятной для чтения человеку. Это называется принцип повторного использования кода. Один из краеугольных камней современного программирования.
Заметьте, что в нашем примере мы запускаем функцию sqr внутри функции ask_and_calc, а её внутри main. Так что как видите, запуск одной функции внутри другой - это нормально и удобно.
При каждом запуске функции для всех её переменных заново выделяется память, а когда функция заканчивается - эта память освобождается под нужды других программ. Все числа нужно хранить где-то в памяти, а нужны они только на время выполнения функции.
Более точно можно сказать, что переменная объявленная внутри блока фигурных скобок в функции, в операторе if или в цикле "живёт" только до конца этого блока, то есть пока не будет достигнута закрывающая фигурная скобка. Блок из фигурных скобок задаёт "область жизни", а также "область видимости" переменной. Область жизни, потому что вне блока память, выделенная под переменную, уже освобождена. Область видимости, потому что к этой переменной больше не имеет смысла обращаться, и для компилятора эта переменная больше не видна.
Это правило даёт нам возможность в разных функциях называть переменные одинаковыми именами. Это бывает удобно, например, любой ответ пользователя на вопрос можно поместить в переменную answer, по-английски "ответ". В одной функции answer будет означать ответ на один вопрос, а в другой функции уже совсем на другой.
То же самое касается параметров функций. В разных функциях могут быть параметры с одинаковым названием, но это их никак не связывает, каждый выполняет свою задачу для своей функции.
Вы дочитали тему до конца - это успех :) Пришло время решать задачи. Ответьте на несколько вопросов, чтобы лучше усвоился новый материал:
#10 – Функции в языке Джава
Функции выполняют роль небольших подпрограмм, что могут содержать повторяющийся код из проекта. В языке Джава можно использовать встроенные функции и создавать свои собственные. За урок мы научимся разрабатывать свои функции (методы) в языке Джава.
Видеоурок
Функции можно назвать небольшими подпрограммами, куда можно вынести повторяющийся код и обращаться к нему, когда это будет нужно. Функции значительно облегчают построение программ, так как нам не надо копировать однотипный код множество раз, а можно просто воспользоваться одной общей функцией.
Многие путают функции и методы и не понимают отличий между ними. На самом деле отличий нет, так как что методы, что функции являются одним и тем же. Функции что записаны вне классов называют функциями, а функции что записаны внутри классов называются методами. Поскольку Java это объектно ориентированный язык, то лучше говорить методы, хотя это не имеет никакого значения.
Точно такая же ситуация обстоит с переменным. В классах переменные называются полями, а вне классов - переменными.
Для создания функций необходимо указать возвращаемый тип данных, указать название и параметры. В случае когда функция ничего не возвращает, то указывается тип данных void .
Перед типом данных всегда прописывается модификатор доступа. Сейчас мы их детально рассматривать не будем, так как это тема ООП. В уроке мы будем постоянно устанавливать модификатор public, тем самым будем говорить что функция доступна всем внутри класса.
Зачем static?
Поскольку мы хотим обращаться к функциям напрямую без создания объекта, то мы прописываем ключевое слово static . Оно говорит компилятору что функция принадлежит всему классу, а не конкретным объектам.
В будущем мы более детально ознакомимся с данным модифактором, но пока будем представлять его как удобное слово для обращения к функциям.
Создание функции
На основе всех данных наша функция будет выглядеть следующим образом:
Функция выше не принимает никаких параметров и ничего не возвращает. Она просто пишет слово в консоль. Давайте разнообразим функцию и добавим параметр:
public static void test(String word)
Теперь функция принимает параметр, который будет отображен в консоли.
Если функция должна что-либо вернуть, то прописываем тип данных который будет возвращен. Для возвращения данных используем ключевое слово return :
public static double test(double some_number)
Весь код будет доступен после подписки на проект!
Необходимо оформить подписку на проект, чтобы получить доступ ко всем домашним заданиям
Вам необходимо оформить подписку на сайте, чтобы иметь доступ ко всем большим заданиям. В задание входит методика решения, а также готовый проект с ответом к заданию.
PS: подобные задания доступны при подписке от 1 месяца