JavaRush /Java Blog /Random EN /Method signature

Method signature

Published in the Random EN group
Hello! You have already mastered creating your own classes, with fields and methods. Today we will talk in detail about the methods. We, of course, have done this more than once in our lectures, but we talked mainly about general points. Today we will literally analyze the methods “in parts” - we will find out what they consist of, what options for creating them exist and how all this can be managed :) Let's go!Method signature - 1

Method signature

All code that describes a method is called a method declaration . A method signature includes the method name and parameter types in a specific order. The general appearance of the ad can be described as follows:
модификатор доступа, тип возвращаемого значения, Name метода(список параметров) {
    // тело метода
}
Let's take an example of declarations of several methods of the class 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("Собака по имени " + name + " говорит \"Гав-гав!\"");
   }

   public void run(int meters) {
       System.out.println("Собака по имени " + name + " пробежала " + meters + " метров!");
   }

   public String getName() {
       return name;
   }
}

1. Access modifier

The access modifier is always listed first. All class methods Dogare designated by the modifier public. That is, we can call them from any other class:
public class Main {

   public static void main(String[] args) {

       Dog butch = new Dog("Бутч");
       butch.run(100);
   }

}
Class methods Dog, as you can see, are easily accessible in the class Main. This is possible thanks to the modifier public. There are other modifiers in Java, and not all of them will allow you to use a method inside another class. We will talk about them in other lectures. The main thing is to remember what the modifier is responsible for: the availability/inaccessibility of the method in other classes :)

2. The static keyword

One of the methods Dog, namely, main()is indicated by the keyword static. If it exists, then it must be specified after the access modifier. Remember in previous lectures we talked about static class variables? When applied to methods, this word has approximately the same meaning. If a method is specified as static, this means that it can be used without reference to a specific class object. And indeed, to run a static method main()in a class, Dogyou do not need to create an instance Dog; it runs without it. If this method were not static, then to use it we would need to first create an object.

3. Return value.

If our method must return something, then we then indicate the type of the return value. This can be seen in the example of a getter getName():
public String getName() {
   return name;
}
It returns an object of type String. If the method does not return anything, the keyword is specified instead of the type void, as in the method woof():
public void woof() {
   System.out.println("Собака по имени " + name + " говорит \"Гав-гав!\"");
}

Methods with the same name

There are situations when our program requires several options for how a method works. Why don't we create our own artificial intelligence? Amazon has Alexa, Yandex has Alice, so why are we worse? :) In the film about Iron Man, Tony Stark created his own outstanding artificial intelligence - JARVIS Let's pay tribute to the wonderful character and name our AI in his honor :) The first thing we must teach Jarvis - greet people who enter the room (it would be strange if such a great intellect turned out to be impolite).
public class Jarvis {

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
   }
}
Console output:

Добрый вечер, Тони Старк, How ваши дела?
Great! Jarvis knows how to greet someone who enters. Most often, of course, it will be his owner - Tony Stark. But he may not come alone! And our method sayHi()takes only one argument as input. And, accordingly, he will be able to greet only one of those who come, and will ignore the other. Not very polite, agree?:/ In this case, to solve the problem, we can simply write 2 methods in the class with the same name, but with different parameters:
public class Jarvis {

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

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

}
This is called method overloading . Overloading allows our program to be more flexible and accommodate different work options. Let's check how it works:
public class Jarvis {

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

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
Console output:

Добрый вечер, Тони Старк, How ваши дела? 
Добрый вечер, Тони Старк, Капитан Америка, How ваши дела?
Great, both options worked :) However, we did not solve the problem! What if there are three guests? Of course, we can overload the method again sayHi()to accept the names of three guests. But there can be 4 or 5 of them. And so on ad infinitum. Is there another way to teach Jarvis to work with any number of names, without a million method overloads sayHi()? :/ Of course have! Otherwise, would Java be the most popular programming language in the world? ;)
public class Jarvis {

   public void sayHi(String...names) {

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark");
       System.out.println();
       jarvis.sayHi("Tony Stark", "Captain America");
   }
}
The record ( String...names) passed as a parameter allows us to indicate that a certain number of strings are passed to the method. We do not specify in advance how many there should be, so the operation of our method now becomes much more flexible:
public class Jarvis {

   public void sayHi(String...names) {

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

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
   }
}
Console output:

Добрый вечер, Тони Старк, How ваши дела? 
Добрый вечер, Капитан Америка, How ваши дела? 
Добрый вечер, Черная Вдова, How ваши дела? 
Добрый вечер, Халк, How ваши дела?
Inside the method, we loop through all the arguments and output ready-made phrases with names to the console. Here we use a simplified loop for-each(you've already encountered it). It's great because writing String...namesactually means that all passed parameters are put into an array by the compiler. Therefore, namesyou can work with a variable as with an array, including looping through it. Moreover, it will work for any number of transferred lines! Two, ten, even a thousand - the method will work reliably with any number of guests. Much more convenient than doing overloads for all possible options, don’t you agree? :) Let’s give another example of method overloading. Let's add a method to Jarvis printInfoFromDatabase(). It will print information about the person from the database to the console. If the database indicates that a person is a superhero or supervillain, this information will also be displayed on the screen:
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("Также известен How супергерой " + nickname);
       } else {
           System.out.println("Также известен How суперзлодей " + nickname);
       }
   }

   public static void main(String[] args) {
       Jarvis jarvis = new Jarvis();
       jarvis.printInfoFromDatabase("Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington");
       System.out.println();
       jarvis.printInfoFromDatabase("Макс Эйзенхарт. Рост 188см, вес 86 кг.", true, "Магнето");
   }
}
Conclusion:

Лора Палмер. Дата рождения - 22 июля 1972, город Твин Пикс, штат Washington
Макс Эйзенхарт. Рост 188см, вес 86 кг 
Также известен How суперзлодей Магнето
This is how our method works depending on the data we pass into it. Another important point:The order of the arguments matters! Let's say our method takes a string and a number as input:
public class Man {

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

   public static void main(String[] args) {

       sayYourAge("My age - ", 33);
       sayYourAge(33, "My age - "); //error!
   }
}
If a sayYourAge()class method Mantakes a string and a number as input, then this is the order in which they need to be passed in the program! If we pass them in a different order, the compiler will throw an error and the person will not be able to tell his age. By the way, the constructors we covered in the last lecture are also methods! They can also be overloaded (create several constructors with different sets of arguments) and for them the order of passing arguments is also fundamentally important. Real methods! :)

How to call methods with similar parameters

As you know, in Java there is such a word as null. When working with it, it is very important to understand that null is neither an object nor a data type. Imagine we have a class Man and a method introduce()that declares a person's name and age. In this case, age can be conveyed in the form of text, or it can be expressed as a number.
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man sasha = new Man();
       sasha.introduce("Sasha", "двадцать один");

       Man masha = new Man();
       masha.introduce("Мария", 32);
   }
}
We are already familiar with overloading, so we know that the method will work as expected both times:

Меня зовут Саша, мой возраст - двадцать один 
Меня зовут Мария, мой возраст - 32 
But what happens if we pass null as the second parameter, not a string or a number?
public static void main(String[] args) {

   Man victor = new Man();
   victor.introduce("Виктор", null);//Ambiguous method call!
}
We'll get a compilation error! The “Ambiguous method call” error is translated as “ambiguous method call”. Why could it arise and what is the “ambiguity”? It's actually simple. The thing is, we have two variants of the method: with Stringand with Integeras the second argument. But both String, and Integercan be null! For both types (since they are reference types), null is the default value. That is why the compiler in this situation cannot figure out which version of the method it should call. Solving this problem is quite simple. The point is that null can be explicitly converted to a specific reference type. Therefore, when calling a method, you can indicate in parentheses the data type you need for the second argument! The compiler will understand your “hint” and call the required method:
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Метод с двумя строками!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, Integer age) {
       System.out.println("Метод со строкой и числом!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man victor = new Man();
       victor.introduce("Виктор", (String) null);
   }
}
Conclusion:

Метод с двумя строками! 
Меня зовут Виктор, мой возраст - null
But if the numeric parameter were a primitive int, and not an object of a reference type Integer, such an error would not occur.
public class Man {

   public void introduce(String name, String age) {
       System.out.println("Метод с двумя строками!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public void introduce(String name, int age) {
       System.out.println("Метод со строкой и числом!!");
       System.out.println("Меня зовут " + name + ", мой возраст - " + age);
   }

   public static void main(String[] args) {

       Man victor = new Man();
       victor.introduce("Виктор", null);
   }
}
Have you guessed why? If you guessed it, well done :) Because primitives cannot be equal to null. Now the compiler has only one option for calling the method introduce()- with two lines. It is this version of the method that will be processed every time the method is called.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION