JavaRush /Java блог /Java Developer /Методы в Java
Professor Hans Noodles
41 уровень

Методы в Java

Статья из группы Java Developer
Существует один интересный принцип, о котором многие слышали. Он называется “Разделяй и властвуй”. Этот принцип используется во многих сферах человеческой жизни, например, в политике. Он обозначает разделение большого количества разнородных частей в государстве, разжигание и использование вражды между этими частями. Иными словами: создать конфликт между теми, кто потенциально создает угрозу власти. Но мы с вами программисты, поэтому нас интересует исключительно техническая трактовка данного принципа. А звучит она так: “Принцип “Разделяй и властвуй” заключается в разбиении большой задачи на более мелкие до тех пор, пока они не станут элементарными. Затем нужно последовательно решить их и объединить все в одну целую систему. Данная программа должна решать поставленную задачу” То есть, вы просто разбиваете большую задачу на более мелкие, решить которые для вас не составляет проблем. А потом собираете решение в одно большое. Чтобы следовать этому простому и полезному принципу, в Java-программировании используют методы. Методы в Java - 1Например, мы создаем робота-боксера. Для нас важно, чтобы он хорошо двигался, проводил точные удары, а также следил за противником в поисках слабых мест. Будет неудобно писать все это в одном методе main, не так ли? Если мы опишем все в одном методе, будет что-то вроде такого:

метод main() {
// Описание действий шага вперед
подача напряжения в отдельные модули;
поднятие ноги;
перевод в другую точку;
поставить ногу;
перенести вес на другую ногу;
если (противникАтакует()) {
        	// Описание действий уклонения робота.
        	...
} еслиНет {
        	// Описание действий обманного атакующего удара.
        	...
}
// Описание действий шага назад
...
}
А если нам понадобится использовать шаг вперед или удар еще где-либо в программе? Описывать все действия снова? Не подходит. Слишком много повторяющихся строк, в которых легко запутаться. Нам нужно вынести описание деталей действия в отдельный модуль, который будет выполнять шаг робота. И мы можем вызывать метод одной строкой. Как-то так:

метод шагВперед() {
// Описание действий шага вперед
  	подача напряжения в отдельные модули;
  	поднятие ноги;
  	перевод в другую точку;
  	поставить ногу;
  	перенести вес на другую ногу;
}

метод уклонение() {
  	// Действия для уклонения
  	...
}

метод обманныйАтакующийУдар() {
  	// Действия для удара
  	...
}

метод шагНазад() {
  	// Действия для шага назад
  	...
}
 
метод противникАтакует() {
	// Робот проверяет атакует ли противник
}

метод main() {
	шагВперед();
	если (противникАтакует()) {
        	уклонение();
	} еслиНет {
  	  обманныйАтакующийУдар();     	
	}
	шагНазад();
}
Теперь у нас есть разделенный функционал робота, а также компактный и понятный метод main(). Остальные методы также можно разделить на какой-либо функционал, например, обманныйАтакующийУдар можно разделить на методы обманноеДвижение, движениеНог, атака. И их, в свою очередь, на более простые задачи, чтобы в итоге получить набор элементарных. Окей, а теперь напишем это все красиво в таком виде, который примет Java.

  	public static void stepForward() {
  	    // Многострочный код, описывающий
  	    // действия робота для выполнения шага
  	    System.out.println("The robot takes a step forward");
	}

	public static void evasion() {
  	    // Действия для уклонения
  	    System.out.println("Robot shy of impact");
	}

	public static void deceptiveAttackBlow() {
  	    // Действия для удара
  	    System.out.println("The robot performs a deceptive strike");
	}

	public static void stepBack() {
  	    // Действия для шага назад
  	    System.out.println("The robot takes a step backwards");
	}

	public static void main(String[] args) {
    	stepForward();
    	if (isEnemyAttacked()) {
        		evasion();
    	} else {
  	    	deceptiveAttackBlow();       	
    	}
    	stepBack();
	}
	
	public static boolean isEnemyAttacked() {
    	// Метод проверяет, атакует ли враг. Возвращает логическое значение.
    	return true;
	}
Понимаю, что вам может быть сейчас этот код немного непонятен, особенно некоторые слова вроде void, return и так далее. Не спешите бросаться помидорами, сейчас все объясню. Общая мысль парадигмы “Разделяй и властвуй” вам должна быть понятна. В этом нам помогут методы. Общая структура объявления методов такая:

модификатор_доступа возвращаемое_значение имя_метода(принимаемые_параметры) {
   	//Тело метода
}

Модификатор доступа

Модификатор доступа — это несколько ключевых слов: public, private, package. Эти слова указывают на область видимости метода. Я объясню просто: этим словом вы как будто делитесь с другими вкусняшкой. Вкусняшка — ваш метод. Если это private, вы не делитесь методом с другими классами. Если package, вы делитесь только с классами в рамках пакета (классы собираются в определенные пакеты, это вы узнаете дальше). Ну а public показывает, что вы — сама доброта и делитесь вкусняшкой (методом) со всей программой. Как-то так. Через несколько уровней вы гораздо лучше поймете роль этих слов.

Возвращаемое значение

Посмотрите пример выше: все методы помечены ключевым словом void, кроме одного — isEnemyAttacked, который возвращает логическое значение boolean. Если метод помечен как void, он может ничего не возвращать. Такой метод просто выполняет набор действий и все. А теперь обратите внимание на метод main. Те методы, которые возвращают void, вызываются просто так, в теле метода. А вот метод isEnemyAttacked вызывается в скобках оператора if. Благодаря тому, что он возвращает логическое значение, мы получаем возможность не использовать промежуточную переменную, а вставлять его напрямую. Возврат значения происходит с помощью ключевого слова return. Если метод возвращает тип int, мы можем вызывать метод из любого выражения:

    public static int getNumber() {
 	    return 5;
	}

	public static void main(String[] args) {
    	int result = 5 + 6 + getNumber();
    	System.out.println(result);
	}
Вывод:
16
Метод getNumber возвращает значение типа int, поэтому мы можем вызывать его из выражения. Также метод может возвращать любой тип, включая те, которые вы создали сами. Если вы указали тип возвращаемого значения у метода, то вы обязаны вернуть что-либо. Нельзя написать так:

    	   public static int findMaxNumber(int a, int b) {
      	if(a>b) {
      	    return a;
      	}
     }
Компилятор будет ругать вас, что при выполнении первого условия вы что-то возвращаете, а при выполнении второго — нет.

Передача параметров

В метод можно передавать параметры, которые используются при его работе. Самый примитивный пример — суммирование двух чисел. Но мы же не примитивные, верно? Возьмем другой пример, достаточно стереотипный. Допустим, у нас есть метод chef() — повар. Мы можем передать в блоке параметров в этот метод ингредиенты супа, и в итоге этот метод возвращает нам суп. Вот так:

	public static void main(String[] args) {
    	String[] ingredients;
    	// Инициализация массива ингредиентов
    	Soup soup = chef(ingredients);
    	
	}
	
	public static Soup chef(String[] ingredients) {
    	Soup soup = new Soup();
    	// Процесс варки супа
    	return soup;
	}
(Допустим, у нас есть заранее созданный класс Soup) В главном методе мы создаем массив ингредиентов, а затем “отдаем его повару” (передаем в метод chef). “Повар варит суп”, а затем возвращает его нам в виде объекта класса Soup. Все очень просто. В метод можно передавать любые параметры, примитивные типы, объекты, массивы и так далее.

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

В языке программирования Java любые параметры передаются в метод по своему значению. Однако для примитивных типов и для объектов этот механизм различен. Если вы передадите в метод любой примитивный тип и измените его, он не изменится в основном методе. Вы просто отдали копию значения, а оригинальная переменная сохранилась. Самый простой пример:

public static void main(String[] args) {
    	int x = 1;
    	System.out.println(x);
    	getNumber(x);
    	System.out.println(x);
    	
	}
	
	public static void getNumber(int i) {
    	i = i + 100;
	}
Вывод:
1 1
Однако в случае с объектами изменения затрагивают оригинальный объект:

public class Program
{
	public static void main(String[] args) {
    	WiseMan wiseMan = new WiseMan();
    	wiseMan.setIq(300);
    	System.out.println(wiseMan);
    	changeObject(wiseMan);
    	System.out.println(wiseMan);
    	
	}
	
	public static void changeObject(WiseMan m) {
    	m.setIq(100);
	}
}

public class WiseMan {
	int iq;
	
	public void setIq(int iq) {
    	this.iq = iq;
	}
	
	public int getIq() {
    	return iq;
	}
	
	public String toString() {
    	return "Our wise man has an IQ "+iq;
	}
}
Вывод:
Our wise man has an IR 300 Our wise man has an IR 100
У нас есть класс WiseMan (Мудрец), который имеет свойство iq. И два метода, которые управляют значением этого поля. В главном методе мы создаем объект wiseMan, устанавливаем значение iq 300. Затем мы передаем в метод changeObject нашего мудреца с iq 300. Но в этом методе он глупеет. Мы устанавливаем значение iq, равное 100. Затем в главном методе выводим объект. Видно, что в методе changeObject мы манипулируем другим мудрецом в переменной m. Однако мы изменяем наш первоначальный объект. Дело в том, что объект wiseMan в главном методе и объект m, в методе changeObject — один и тот же мудрец, а в метод в качестве параметра копируется ссылка на объект. Помните об этом, когда будете редактировать объект в отдельных методах.

Напоследок несколько слов о модификаторе static

Вообще, несколькими словами здесь не обойтись, но я попробую. Обычные методы, не помеченные данным модификатором, принадлежат объекту класса. А static-методы принадлежат самому классу. Обычные методы можно использовать у отдельных объектов. Посмотрите на класс WiseMan из примера выше. Методы getIq и setIq у каждого мудреца будут свои, ведь уровень айкью у всех разный. Если мы добавим в этот класс static метод generateAWisePhrase, то такой метод мы сможем вызывать без объекта:

WiseMan.generateAWisePhrase();
В общем, этой информации пока достаточно, ведь о static можно написать несколько лекций. Придерживайтесь нескольких правил при написании метода для поддержания порядка в своем коде:
  • Придумывайте своим методам говорящие названия, чтобы было ясно, что они делают.
  • Старайтесь не писать очень длинных методов. Оптимальная длина — 8-15 строк.
  • Количество параметров метода не должно превышать 4-5.
  • Если в вашем коде дважды встречается похожий функционал, подумайте: может, стоит обобщить, вынести его в отдельный метод?
Эти способы помогут вам повысить производительность вашей программы и, самое главное, сделают ваш код более читабельным.
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Екатерина Уровень 6
15 ноября 2021
ссложно