CodeGym /Java блог /Случаен /Декларация на метод
John Squirrels
Ниво
San Francisco

Декларация на метод

Публикувано в групата
здрасти Вече знаете за създаването на ваши собствени класове с полета и методи. Сега ще се спрем на методите.
Декларация на метод - 1
Разбира се, вече сме правor това повече от веднъж в нашите уроци, но сме обхванали основно общи неща. Днес ще анализираме методите и ще проучим от Howво са напequalsи, различните начини за създаването им и How да управляваме всичко това. :) Да тръгваме!

Декларация на метод

Целият code, който дефинира метод, се нарича декларация на метод . Общата форма на декларация на метод може да бъде описана по следния начин:

access modifier, return type, method name (parameter list) {
    // method body
}
Като примери, разгледайте декларациите на различните методи на Dogкласа.

public class Dog {

   String name;

   public Dog(String name) {
       this.name = name;
   }

   public static void main(String[] args) {
       Dog max = new Dog("Max");
       max.woof();

   }

   public void woof() {
       System.out.println("A dog named " + name + " says \"Woof, woof!\"");
   }

   public void run(int distanceInFeet) {
       System.out.println("A dog named " + name + " ran " + distanceInFeet + " feet!");
   }

   public String getName() {
       return name;
   }
}

1. Модификатор на достъп

Модификаторът за достъп винаги се посочва първи. Всички Dogметоди на класа са маркирани с публичен модификатор. Това означава, че можем да ги извикаме от всеки друг клас:

public class Main {

   public static void main(String[] args) {

       Dog butch = new Dog("Butch");
       butch.run(100);
   }

}
Както можете да видите, Dogметодите на класа са лесно достъпни в Mainкласа. Това е възможно благодарение на публичния модификатор. В Java има и други модификатори. Не всички позволяват използването на методи в други класове. Ще говорим за тях в други уроци. Основното нещо, което трябва да запомните, е за Howво отговаря модификаторът: дали даден метод е достъпен в други класове :)

2. статична ключова дума

Един от Dogметодите, main(), е маркиран с ключовата дума static . Това също е част от декларацията на метода и вече знаем meaningто му. Не го споменахме в шаблона за декларация на метода, даден в началото на урока, защото не е задължителен. Ако е посочено, то трябва да идва след модификатора за достъп. Помните ли, че в последните уроци говорихме за статични (класови) променливи? Когато се прилага към методи, тази ключова дума има приблизително същото meaning. Ако даден метод е статичен , тогава той може да се използва без препратка към конкретен обект от класа. И наистина, нямате нужда от Dogобект, за да изпълните статичния main()метод вDogклас. Ще работи добре и без такъв. Ако този метод не беше статичен, тогава първо трябваше да създадем обект, за да го стартираме.

3. Върната стойност

Ако нашият метод трябва да върне нещо, ние определяме типа на върнатата стойност. Това е видно от примера на getName()getter:

public String getName() {
   return name;
}
Връща Stringобект. Ако даден метод не върне нищо, instead of това се използва ключова дума voidwoof() , Howто в метода:

public void woof() {
   System.out.println("A dog named " + name + " says \"Woof, woof!\"");
}

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

Има ситуации, когато ще искаме няколко различни начина за извикване на метод. Защо не създадем собствен изкуствен интелект? Amazon има Alexa, Apple има Siri, така че защо да не имаме и ние? :) Във филма Железният човек Тони Старк създава свой собствен невероятен изкуствен интелект Джарвис. Нека отдадем почит на този страхотен герой и назовем нашия AI в негова чест. :) Първото нещо, което трябва да направим, е да научим Джарвис да поздравява хората, които влизат в стаята (би било странно, ако такъв невероятен интелект се окаже неучтив).

public class Jarvis {

   public void sayHi(String name) {
       System.out.println("Good evening, " + name + ". How are you?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
   }
}
Изход от конзолата: Добър вечер, Тони Старк. Как си? Много добре! Джарвис вече може да посреща гости. Разбира се, по-често, отколкото ще бъде неговият господар, Тони Старк. Но Howво като не дойде сам! Но нашият sayHi()метод приема само един аргумент. И така може да поздрави само един човек, влизащ в стаята, и ще игнорира другия. Не е много учтиво, съгласни ли сте? :/ В този случай можем да решим проблема, като просто напишем 2 метода с едно и също име, но различни параметри:

public class Jarvis {

   public void sayHi(String firstGuest) {
       System.out.println("Good evening, " + firstGuest + ". How are you?");
   }

   public void sayHi(String firstGuest, String secondGuest) {
       System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
   }

}
Това се нарича претоварване на метода . Претоварването на методите позволява на нашата програма да бъде по-гъвкава и да побира различни начини на работа. Нека прегледаме How работи:

public class Jarvis {

   public void sayHi(String firstGuest) {
       System.out.println("Good evening, " + firstGuest + ". How are you?");
   }

   public void sayHi(String firstGuest, String secondGuest) {
       System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
Изход от конзолата: Добър вечер, Тони Старк. Как си? Добър вечер, Тони Старк и Капитан Америка. Как си? Отлично, и двете версии работят. :) Но не решихме проблема! Ами ако гостите са трима? Можем, разбира се, да претоварим sayHi()отново метода, така че да приема три имена на гости. Но може да има 4 or 5. Чак до безкрайност. Няма ли по-добър начин да научите Джарвис да борави с произволен брой имена, без да претоварвате метода sayHi()мorон пъти()? :/ Разбира се, че има! Ако го нямаше, мислите ли, че Java щеше да е най-популярният език за програмиране в света? ;)

public class Jarvis {

   public void sayHi(String...names) {

       for (String name: names) {
           System.out.println("Good evening, " + name + ". How are you?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       System.out.println();
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
Когато ( String... names ) се използва като параметър, това показва, че колекция от низове ще бъде предадена на метода. Не е нужно да уточняваме предварително колко ще бъдат, така че сега нашият метод е много по-гъвкав:

public class Jarvis {

   public void sayHi(String...names) {

       for (String name: names) {
           System.out.println("Good evening, " + name + ". How are you?");
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
   }
}
Изход от конзолата: Добър вечер, Тони Старк. Как си? Добър вечер, Капитан Америка. Как си? Добър вечер, черна вдовица. Как си? Добър вечер, Хълк. Как си? Вътре в метода ние обикаляме всички аргументи и показваме фрази, форматирани с имена. Тук използваме опростен for-eachцикъл (който сте виждали преди). Тук е перфектно, защото нотацията ( String... names ) всъщност означава, че компилаторът поставя всички предадени аргументи в масив. В резултат на това можем да работим с имена на променливиHowто бихме работor с масив, включително чрез итерация през него в цикъл. Освен това ще работи с произволен брой предадени низове! Двама, десет, дори хиляда - методът ще работи правилно с произволен брой гости. Много по-удобно от претоварването на метода за всички възможности, не мислите ли? :) Ето още един пример за претоварване на метода. Нека дадем на Джарвис printInfoFromDatabase()метод. Той ще покаже информация за човек от база данни. Ако базата данни показва, че даден човек е супергерой or суперзлодей, ние ще покажем тази информация:

public class Jarvis {

   public void printInfoFromDatabase (String bio) {

       System.out.println(bio);
   }

   public void printInfoFromDatabase(String bio, boolean isEvil, String nickname) {

       System.out.println(bio);
       if (!isEvil) {
           System.out.println("Also known as the superhero " + nickname);
       } else {
           System.out.println("Also known as the supervillain " + nickname);
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.printInfoFromDatabase("Laura Palmer. Date of birth: July 22, 1972. Twin Peaks, Washington");
       System.out.println();
       jarvis.printInfoFromDatabase("Max Eisenhardt. Height: 15.6 ft. Weight: 189 lbs. ", true, "Magneto");
   }
}
Резултат: Лора Палмър. Дата на раждане: 22 юли 1972 г. Туин Пийкс, Washington Макс Айзенхард. Височина: 15,6 фута Tagло: 189 фунта. Известен също като суперзлодеят Магнито И така, поведението на нашия метод зависи от данните, които му предаваме. Ето още един важен момент: редът на аргументите има meaning! Да кажем, че нашият метод приема низ и число:

public class Person {

   public static void sayYourAge(String greeting, int age) {
       System.out.println(greeting + " " + age);
   }

   public static void main(String[] args) {

       sayYourAge("My age is ", 33);
       sayYourAge(33, "My age is "); // Error!
   }
}
Ако методът Personна класа sayYourAge()приема низ и число като вход, тогава това е редът, в който тези аргументи трябва да бъдат предадени на метода! Ако ги подадем в различен ред, тогава компилаторът ще генерира грешка и човекът няма да може да каже възрастта си. Между другото, конструкторите, които разгледахме в миналия урок, също са методи! Можете също така да ги претоварите (т.е. да създадете няколко конструктора с различни набори от параметри) и редът на предаваните аргументи също е фундаментално важен за тях. Това са истински методи! :)

Как да извикате методи с подобни параметри

Както знаете, nullе ключова дума в Java. Много е важно да се разбере, че това nullне е нито обект, нито тип данни . Представете си, че имаме Personклас и introduce()метод, който съобщава името и възрастта на лицето. Освен това възрастта може да бъде предадена като текст or число.

public class Person {

   public void introduce(String name, String age) {
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person alex = new Person();
       alex.introduce ("Alex", "twenty-one");

       Person mary = new Person();
       mary.introduce("Mary", 32);
   }
}
Вече сме запознати с претоварването, така че знаем, че и двата метода ще се държат Howто трябва: Казвам се Алекс. Моята възраст е двадесет и една Казвам се Мери. Моята възраст е 32. Но Howво ще се случи, ако подадем nullкато втори параметър instead of низ or число?

public static void main(String[] args) {

   Person victor = new Person();
   victor.introduce("Victor", null);// Ambiguous method call!
}
Ще получим грешка при компилация! На Howво се дължи това и Howва точно е "неяснотата"? Всъщност всичко е много просто. Проблемът е, че имаме две версии на метода: една с a Stringкато втори аргумент и една с an Integerкато втори аргумент. Но Stringи двете Integerмогат да бъдат null! Тъй като те са референтни типове, nullе стойността по подразбиране и за двата. Ето защо в тази ситуация компилаторът не може да разбере коя version на метода трябва да извика. Решението на този проблем е съвсем просто. Nullможе изрично да се преобразува в конкретен референтен тип. По този начин, когато извиквате метод, можете да посочите в скоби типа данни, който искате за втория аргумент! Компилаторът ще разбере вашия "намек" и ще извика правилния метод:

public class Person {

   public void introduce(String name, String age) {
       System.out.println("Method with two strings!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Method with a string and a number!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person victor = new Person();
       victor.introduce("Victor", (String) null);
   }
}
Резултат: Метод с два низа! Казвам се Виктор. My age is null Имайте предвид, че ако числовият параметър беше примитивен int, а не екземпляр на референтния тип Integer, нямаше да има такава грешка.

public class Person {

   public void introduce(String name, String age) {
       System.out.println("Method with two strings!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public void introduce(String name, int age) {
       System.out.println("Method with a string and a number!!");
       System.out.println("My name is " + name + ". My age is " + age);
   }

   public static void main(String[] args) {

       Person victor = new Person();
       victor.introduce("Victor", null);
   }
}
Можете ли да познаете защо? Ако сте познали защо, браво! :) Защото примитивите не могат да бъдат null. Сега компилаторът има само един избор, т.е. да извика introduce()метода с два низа. Това е versionта на метода, която ще се изпълнява при всяко извикване на метода.
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION