"Здравей, амиго! Надявам се, че ти хареса да решаваш задачи, използвайки свои собствени методи, и че осъзнаваш колко удобно е да създаваш методи. Сега нека поговорим за най-интересната тема от всички."

— Събуди интереса ми, Диего... Нова тема?

„Всяка тема е нова за теб, млади мой робот! И тази не е изключение. Въпреки че отново става дума за методи. Вероятно вече си забелязал от такива методи, че можем да предаваме аргументи на методи. Щом влезем в System.out.println()метода , ние ги наричаме параметри."

„Параметрите са това, което пишем в скобите?“

"Да, точно така. И всъщност параметрите значително подобряват ползите, които получаваме от създаването и използването на методи."

„Разбрах Howво искаш да кажеш за използването им и се оказа, че вече съм го направил. Как да декларираме метод с параметри?“

„Всъщност е много просто:

public static void name(parameters)
{
  method body
}

„Къде nameе уникалното име на метода и method bodyпредставлява командите, които съставят метода. И parametersе контейнер за параметрите на метода, разделени със запетаи.“

"Хм... мисля, че разбирам... Или може би не..."

„Позволете ми да ви дам още подробности за този шаблон, за да сте сигурни, че разбирате, че разбирате:

public static void name(Type1 name1, Type2 name2, Type3 name3)
{
  method body
}

Ето няколко примера:

Код Обяснение
public static void print(String str)
{
}
Методът printсе декларира с параметър:
String str
public static void print(String str, int count)
{
}
Методът printсе декларира с два параметъра:
String str
int count
public static void write(int x, int y)
{
}
Методът writeсе декларира с два параметъра:
int x
int y

"А... Сега е ясно. И ако не искаме методът да има параметри, тогава просто оставяме скобите празни."

„Точно така. По принцип параметрите са специални променливи в рамките на метод. С тяхна помощ можете да предавате различни стойности на метода, когато се извиква. И ако не е необходимо да предавате стойности, тогава оставяте скобите празни.

"Например, нека напишем метод, който показва даден ред текст определен брой пъти. НяHowви мисли How да направите това?"

„Ами... Изглежда, че съм наясно How да напиша code, който да показва низ на екрана няколко пъти...“

"Как определяте низа, който да се показва? И How определяте броя на показаните редове? Можете ли да познаете?"

„Нещата започват да се изясняват... Вероятно с помощта на параметрите на метода?“

„Точно така. Низов параметър за реда от текст и цифров параметър за броя на показаните редове. Кодът, който прави това, ще изглежда така:

Код Обяснение
class Solution
{
   public static void printLines(String text, int count)
   {
     for (int i = 0; i < count; i++)
       System.out.println(text);
   }

   public static void main(String[] args)
   {
     printLines("Hi", 10);
     printLines("Bye", 20);
   }
}

Декларирахме printLinesметода със следните параметри:
String text, int count

Методът показва text countвремена на низове



. Извикваме printLinesметода с различни параметри

„Всеки път, когато се извика метод, на неговите параметри се присвояват предадените стойности и едва тогава започваме да изпълняваме командите вътре в метода.

Аргументи

„Искам да обърнете специално внимание на извикването на методи, които имат параметри. Стойностите, предавани на метода, обикновено се наричат ​​аргументи, когато се предават на метода.

Нека да погледнем отново нашия пример:

Код Обяснение
class Solution
{
   public static void printLines(String text, int count)
   {
     for (int i = 0; i < count; i++)
       System.out.println(text);
   }

   public static void main(String[] args)
   {
     printLines("Hi", 10);
     printLines("Bye", 20);
   }
}

Декларирахме printLinesметода със следните параметри:
String text, int count

Методът показва String text countпъти


. Извикваме printLinesметода със следните аргументи:
text = "Hi"; count = 10;
text = "Bye"; count = 20;

„Когато printLinesметодът беше извикан за първи път, на неговите параметри бяха присвоени следните стойности:

String text = "Hi", int count = 10.

„Когато printLinesметодът беше извикан втори път, на параметрите му бяха присвоени различни стойности:

String text = "Bye", int count = 20.

„Параметрите са не повече и не по-малко от променливи, на които се присвояват определени стойности, когато се извиква метод. Самите стойности "Hi", "Bye", 10и 20се наричат ​​аргументи.“

„Ще се опитам да запомня разликата и да не бъркам тези понятия.“

Конфликтни имена на променливи при извикване на метод

„Когато извиквате метод, можете да използвате променливи като аргументи.

— Е, това има смисъл!

„Има смисъл, но потенциално може да създаде някои трудности. Нека се върнем отново към нашия пример, но този път ще преместим аргументите в отделни променливи:

Код Обяснение
class Solution
{
   public static void printLines(String text, int count)
   {
     for (int i = 0; i < count; i++)
       System.out.print(text);
   }

   public static void main(String[] args)
   {
     String str = "Hi";
     String n = 10;
     printLines(str, n);
   }
}

Декларирахме printLinesметода със следните параметри:
String text, int count

Методът показва String text countпъти



. Извикваме printLinesметода със следните аргументи:
text = str;
count = n;

"Хм... Не виждам ниHowви затруднения. Имаме променлива str. Нейната стойност се присвоява на textпараметъра, когато се извиква методът. Имаме променлива n. Нейната стойност се присвоява на countпараметъра, когато се извиква методът." — Засега всичко е ясно.

„Добре, добре. Сега нека преименуваме нашите променливи в mainметода:

Код Обяснение
class Solution
{
   public static void printLines(String text, int count)
   {
     for (int i = 0; i < count; i++)
       System.out.print(text);
   }

   public static void main(String[] args)
   {
     String text = "Hi";
     String count = 10;
     printLines(text, count);
   }
}

Декларирахме printLinesметода със следните параметри:
String text, int count

Методът показва String text countпъти



. Извикваме printLinesметода със следните аргументи:
text = text;
count = count;

„Обърнете внимание на две неща

Първо: имаме променливи с едно и също име в различни методи. Това са различни променливи (умишлено ги изобразяваме с различни цветове). Всичко работи по същия начин, Howто в предишния пример, където променливите в mainметода са именувани strи n.

Второ: Нищо магическо не се случва, когато методът бъде извикан. На параметрите просто се присвояват стойностите на аргумента. Независимо дали са числа, низове, променливи or изрази.

"След като преименувахме променливите в основния метод, нищо не се е променило. Те бяха различни променливи в различни методи преди това и така си остават. Няма магическа връзка между двете textпроменливи."

"Сега знам."

Предаване на препратки към методи

„Надявам се, че вече сте усвоor всичко, което ви казах за предаването на аргументи към методите. Казвам го, защото сега ще се потопим малко по-дълбоко в тази тема. Слушайте внимателно.“

„Вече знаете, че някои променливи в Java съхраняват не самите стойности, а instead of това препратка , т.е. address на блока от паметта, където се намират стойностите. Ето How работят променливите с низове и променливите с масиви.

„Какво се случва, когато разработчик присвои друга променлива от масив на променлива от масив?“

„Те тогава сочат ли към същия address?“

„Правилно. Двете променливи започват да се отнасят към едно и също пространство в паметта:

„И Howво се случва, ако една от тези променливи е параметър на метод?

Код Обяснение
class Solution
{
   public static void sum(int[] data)
   {
     int total = 0;
     for (int i = 0; i < data.length; i++)
       total = total + data[i];
     System.out.println(total);
   }

   public static void main(String[] args)
   {
     int[] months = {31, 28, 31, 30, 31, 30, 31, 31, 30};
     sum(months);
   }
}


Методът sumизчислява сбора на числата в предадения масив и го показва на екрана

„Случва се абсолютно същото: dataпараметърът ще съдържа препратка към същата област от паметта като променливата months. Когато методът бъде извикан, възниква просто присвояване: .data = months

„И тъй като и двете променливи се отнасят до една и съща област от паметта, съхраняваща цяло число, тогава методът sumможе не само да чете стойности от масива, но и да ги променя!“

„Предполагам, че разбирам, но имам нужда от още примери!“

„Ами, например, можем да напишем наш собствен метод, който запълва двуизмерен масив със същата стойност. Ето How може да изглежда:

Код Обяснение
class Solution
{
   public static void fill(int[][] data, int value)
   {
     for (int i = 0; i < data.length; i++)
     {
       for (int j = 0; j < data[i].length; j++)
         data[i][j] = value;
     }
  }

   public static void main(String[] args)
   {
     int[][] months = {{31, 28}, {31, 30, 31}, {30, 31, 31}};
     fill (months, 8);
   }
}


Методът fill итерира всяка клетка в предадения двуизмерен масив и присвоява valueкъм тях.






Създаваме двуизмерен масив.
Запълваме целия масив с числото 8.

Методи със същото име

„А сега да се върнем отново към имената на методите.“

„Не мога да си представя Howво друго може да се каже за имената!“

„Е, стандартът на езика Java изисква всички методи в един и същи клас да имат уникални имена.

„Така че е невъзможно да се декларират два метода с еднакви имена в един и същи клас?“

„Сега – обърнете внимание! Методите в един клас наистина могат да имат еднакви имена! Но в този случай те трябва да имат различни параметри. С други думи, методите се сравняват за еднаквост, не само имената се вземат предвид, но и типовете на параметрите !Имайте предвид, че специално казах типове. Имената на параметрите не се вземат под внимание Примери:

Код Обяснение
void fill(int[] data, int value) {
}
void fill(int[][] data, int value) {
}
void fill(int[][][] data, int value)  {
}
Тези три метода са различни методи. Те могат да бъдат декларирани в един и същи клас.
void print(String str) {
}
void print(String str, String str2) {
}
void print(int val) {
}
void print(double val) {
}
void print() {
}
Всеки от тези пет метода се счита за различен . Те могат да бъдат декларирани в един и същи клас.
void sum(int x, int y) {
}
void sum(int data, int value) {
}
"Тези два метода се считат за еднакви , което означава, че не могат да бъдат декларирани в един и същи клас."

"Напълно съм объркан! Защо имаме нужда от всичко това? Защо някои методи се считат за еднакви , докато други са различни ? И защо имената на параметрите не се вземат предвид при определяне на уникалността на метод? Защо е необходима уникалност при всичко?"

„Работата е там, че когато компилаторът компorра програма, той трябва да знае точно кой метод възнамерявате да извикате на дадено място.

„Например, ако напишете , компилаторът е умен и лесно ще заключи, че възнамерявате да извикате метода тук с параметър. Но ако напишете , компилаторът ще види извикване на метода с параметър. Той няма представа Howво име е дал програмистът на параметъра при декларирането на метода."System.out.println("Hi")println()StringSystem.out.println(1.0)println()double

Ааа, май започва да се проявява!

„Когато се извика метод, компилаторът гарантира, че типовете на аргументите съответстват на типовете на параметрите. Той не обръща внимание на името на аргументите. В Java имената на параметрите не помагат на компилатора да определи кой метод да Програмистите се нуждаят от тях, не от компилатора.

„И предполагам, че затова не се вземат предвид, когато се определя уникалността на даден метод?“

„Да, това е напълно правилно. Името на метод и типовете на неговите параметри се наричат ​​сигнатура на метода . Например, sum (int, int)

„Така че всеки клас трябва да има методи с уникални сигнатури , а не методи с уникални имена.“

"Браво, Амиго! Обобщихте идеално този урок. Ако нещо остане неясно, не се паникьосвайте. Тази тема ще стане ясна след няколко задачи."