Найти в Дзене
Изучаем Java

Java09: методы

С методами мы уже неоднократно встречались на передыдущих уроках. В каждом примере у нас был метод main: Метод main - это точка входа, с которой начинается выполнение программы.
String[] args - это аргументы командной строки, с которыми запускается приложение. Напишем небольшую программу, которая выводит кол-во аргументов и сами аргументы: Мы могли бы записать весь код только в одном методе main и, в теории, могли бы так написать любую программу, но проблема в том, что все это постепенно заняло бы несколько страниц кода. Все это сложно понять и удержать в голове. Но мы можем разбить нашу большую “проблему”, на маленькие кусочки и дробить все это до такого уровня, где со сложностью уже можно иметь дело. Одна из техник подразумевает, что мы можем разбить наш код на отдельные небольшие методы, в которых уже будем иметь дело с локальными кусочками большой задачи. Для примера разобьем на отдельные методы пример с опросником из предыдущего урока: Тот же исходник, но текстом (ссылка на исходн
Оглавление

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

Метод main - это точка входа, с которой начинается выполнение программы.
String[] args - это аргументы командной строки, с которыми запускается приложение.

Напишем небольшую программу, которая выводит кол-во аргументов и сами аргументы:

-2

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

Но мы можем разбить нашу большую “проблему”, на маленькие кусочки и дробить все это до такого уровня, где со сложностью уже можно иметь дело.

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

Для примера разобьем на отдельные методы пример с опросником из предыдущего урока:

-3
Тот же исходник, но текстом (ссылка на исходник).

Мы вынесли в отдельные методы код, который задает вопросы - askQuestions, и код, который распечатывает ответы - printAnswers.

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

  • название метода должно отображать, что он делает
  • задача локализованная внутри метода, должна быть достаточно узкой, внутри метода не распыляться и делать что-то одно
  • задокументировать метод

Под документированием метода подразумеваем либо пару коментариев об особенностях метода, либо более полное описание метода с использованием тегов Javadoc

Рассмотрим подробнее декларацию (объявление) метода:

-4
  • static - специальный модификатор, рассмотри позже вместе с классами
  • void - маркер, показывает, что метод не возвращает результат
  • String[]titles, String[] answers - входные параметры

В общем виде объявление метода:

-5
  • <модификаторы_доступа> - static, public, private, protected, package-private
  • <тип_выходного_параметра> - тип переменной, которую возвращаем из метода (примитивы, массивы или классы), либо void (специальный маркер, что ничего не возвращаем)
  • <список_параметров_метода> - отдельные именованные параметры (аналогично переменным), либо вариант с переменным числом параметров

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

Например здесь на выходе void, оператора return нет

-6

из метода выходим по закрывающей скобке.

Но мы можем, к примеру, добавить проверку входных параметров при старте метода и выйти раньше по оператору return:

-7

Если метод возвращает какое-то значение (не void), то выход из него должен быть выполнен с помощью оператора return с указанием значения, которое мы возвращаем.

Например:

-8

В Java под сигнатурой метода понимается название метода и набор входных параметров.

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

Вспомните метод println стандартной библиотеки, который мы постоянно используем:

-9

одно и тоже название, но разный набор параметров (см. println ).

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

Так же есть возможность передать в метод опциональное число параметров. Для параметра используется синтаксис <тип>... <название_аргумента>.

Например напишем метод, который складывает произвольное число параметров:

-10

здесь int... args это фактически массив int.

Передача по значению и по ссылке

Входные параметры передаются в метод по значению, либо по ссылке.

С практической точки зрения, если мы меняем параметр, который передали по ссылке, то изменения заметны снаружи метода, а для параметров переданных по значению - нет.

По значению передаются только примитивные типы, все остальные (массивы, классы) - по ссылке.

Пример передачи параметра по значению:

-11

Мы присваиваем переменой x значение 10, передаем в метод changeInt, там меняем значение на 1. Дальше после завершения метода проверяем значени x(печатаем) и видим, что значение переменной x не изменилось. Все дело в том что в метод передается копия значения и дальше мы имем дело с локальной копией (переменная int a).

А вот пример, когда мы передаем массив (т.е. по ссылке) и меняем его содержимое:

-12

Рекурсия

Так же методы обладают такой возможностью, как рекурсия т.е. возможностью вызвать сами себя.

Например напишем метод, который распечатает заданный диапазон целых положительных чисел:

-13

Задание:

  • Наберите программу-опросник, которую мы обсуждали в начале урока. Запустите на выполнение. Добавьте вопросов и ответов.

Используя рекурсию, напишите метод printChars, который распечатает каждый символ строковой переменной на отдельной строке.

-14
- получить первый символ в строке str.charAt(0)
-
получить строку, которая меньше текущей на 1 символ str.substring(1)
-
условие выхода из рекурсии str.length() == 0
- распечатать символ на отдельной строке
System.out.println(str[0]); где str - это String str;

Полезные ссылки: