JavaRush/Java Blog/Random EN/Methods, their parameters, interaction and overloading

Methods, their parameters, interaction and overloading

Published in the Random EN group
members
Hello again! In the last lecture, we got acquainted with classes and constructors, and learned how to create our own. Methods, their parameters, interaction and overloading - 1Today we will take a closer look at such an integral part of classes as methods. A method is a set of commands that allows you to perform some operation in a program. In other words, a method is a function; something your class can do. In other programming languages, methods are often called “functions,” but in Java the word “method” has become more popular :) In the last lecture, if you remember, we created simple methods for the Cat class so that our cats could meow and jump:

public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Jumping gallop!");
    }

    public static void main(String[] args) {
        Cat barsik = new Cat();
        barsik.age = 3;
        barsik.name = "Barsik";

        barsik.sayMeow();
        barsik.jump();
    }
}
sayMeow()and jump()are methods of our class. The result of their work is the output to the console:
Мяу!
Прыг-скок!
Our methods are quite simple: they simply print text to the console. But in Java, methods have a main task - they must perform actions on the data of an object . Change the value of an object's data, transform it, output it to the console, or do something else with it. Our current methods don't do anything with the object's data Cat. Let's look at a more clear example:

public class Truck {

    int length;
    int width;
    int height;
    int weight;

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
For example, we have a class that represents a truck - Truck. A truck trailer has a length, width and height, and a weight (this will be needed later). In the method, getVolume()we perform calculations - we transform the data of our object to a number that indicates the volume (we multiply the length, width and height). This is the number that will be the result of the method. Please note - in the description of the method it is written public int getVolume. This means that the result of this method must be a number in the form int. We have calculated the result of the method, and now we must return it to our program that called the method. To return the result of a method in Java, the keyword is used return.

return volume;

Method parameters

Methods can accept values ​​as input, which are called "method parameters". Our current method getVolume()in the class Truckdoes not accept any parameters, so let's try to expand the example with trucks. Let's create a new class - BridgeOfficer. A police officer is on duty on the bridge and checks all passing trucks to ensure that their loads do not exceed the permissible weight limit.

public class BridgeOfficer {

    int maxWeight;

    public BridgeOfficer(int normalWeight) {
        this.maxWeight = normalWeight;
    }

    public boolean checkTruck(Truck truck) {
        if (truck.weight > maxWeight) {
            return false;
        } else {
            return true;
        }
    }
}
The method checkTrucktakes one parameter as input - a truck object Truck, and determines whether the officer will allow the truck onto the bridge or not. The logic inside the method is quite simple: if the weight of the truck exceeds the maximum allowable, the method returns false. You'll have to look for another road :( If the weight is less than or equal to the maximum, you can pass, and the method returns true. If you still do not fully understand the phrases “return”, “method returns a value” - let’s take a break from programming and look at this using a simple example from a real world life :) Let's say you got sick and weren't at work for several days. You come to the accounting department with your sick leave, which you must pay. If we draw an analogy with methods, then the accountant has a method paySickLeave()(“pay sick leave”). You pass a sick leave certificate to this method as a parameter (without it, the method will not work and you will not be paid anything!). Inside the worksheet method, the necessary calculations are made (the accountant uses it to calculate how much the company should pay you), and the result of the work is returned to you - a sum of money. The program works the same way. It calls a method, passes data there and finally receives the result. Here is the method main()for our program BridgeOfficer:

public static void main(String[] args) {
    Truck first = new Truck();
    first.weight = 10000;
    Truck second = new Truck();
    second.weight = 20000;

    BridgeOfficer officer = new BridgeOfficer(15000);
    System.out.println("Truck number 1! May I pass, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck number 2! May I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
We are creating two trucks with loads of 10,000 and 20,000. At the same time, the maximum weight for the bridge where the officer is on duty is 15,000. The program called the method officer.checkTruck(first), the method calculated everything and returned the result to the program - true, and the program saved it in the variable boolean canFirstTruckGo. Now he can do whatever he wants with it (just like you with the money you received from the accountant). Ultimately the code

boolean canFirstTruckGo = officer.checkTruck(first);
comes down to

boolean canFirstTruckGo = true;
A very important point: the operator returnnot only returns the result of the method, but also terminates its work ! All code written after return will not be executed!

public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, overweight!");
    } else {
        return true;
        System.out.println("Alright, move on!");
    }
}
The phrases that the officer says will not be output to the console, because the method has already returned a result and completed its work! The program returned to the point where the method was called. You don't have to worry about this yourself - the Java compiler is smart enough to throw an error if you try to write code after return.

Avengers: Options War

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 entering 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 void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ", How are you doing?");
    }
}
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 ваши дела?
Some of the code here is unfamiliar to you, but don't mind that. Its essence is simple - the method goes through all the names in turn and greets each of the guests! 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? :) 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 sayYourAgeclass 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! :)

And again about the parameters

Yes, yes, we are not done with them yet :) The topic that we will consider now is very important. There is a 90% chance that they will ask about this at all your future interviews! We'll talk about passing parameters to methods. Let's look at a simple example:

public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        currentYear = currentYear-10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2020;

        System.out.println("What is the year now?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And now?");
        System.out.println(currentYear);
    }
}
The time machine has two methods. Both take as input a number representing the current year and either increment or decrement the value (depending on whether we want to go back in time or into the future). But, as can be seen from the console output, the method did not work! Console output:
Какой сейчас год?
2020
А сейчас?
2020
We passed a variable currentYearto the method goToPast(), but its value did not change. As it was in 2020, it remains so. But why? :/ Because primitives in Java are passed to methods by value. What does it mean? When we call a method goToPast()and pass our variable there int currentYear = 2020, it is not the variable itself that gets into the method currentYear, but a copy of it . The value of this copy, of course, is also equal to 2020, but all changes that occur to the copy do not in any way affect our original variablecurrentYear ! Let's make our code more verbose and see what happens with currentYear:

public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        System.out.println("The goToPast method has started!");
        System.out.println("The currentYear value inside the goToPast method (at the beginning) = " + currentYear);
        currentYear = currentYear-10;
        System.out.println("The currentYear value inside the goToPast method (at the end) = " + currentYear);
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2020;

        System.out.println("What is the year at the very beginning of the program?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("What year is it now?");
        System.out.println(currentYear);
    }
}
Console output:
Какой год в самом начале работы программы?
2020
Метод goToPast начал работу!
Значение currentYear внутри метода goToPast (в начале) = 2020
Значение currentYear внутри метода goToPast (в конце) = 2010
А сейчас Howой год?
2020
This clearly shows that the variable that was passed to the method goToPast()is only a copy currentYear. And changing the copy had no effect on the meaning of the “original”. " Passing by reference " has exactly the opposite meaning. Let's practice on cats! I mean, let's see what passing by link looks like using cats as an example :)

public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
Now, with the help of our time machine, we will launch Barsik, the world's first cat-time traveler, into the past and future! Let's change the class TimeMachineso that the machine can work with objects Cat;

public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }    
}
Methods now change not just the passed number, but the field ageof a specific object Cat. In the case of primitives, as you remember, we didn’t succeed: the original number did not change. Let's see what happens here!

public static void main(String[] args) {

    TimeMachine timeMachine = new TimeMachine();
    Cat barsik = new Cat(5);

    System.out.println("How old is Barsik at the very beginning of the program?");
    System.out.println(barsik.age);

    timeMachine.goToFuture(barsik);
    System.out.println("And now?");
    System.out.println(barsik.age);

    System.out.println("Firs-sticks! Barsik has aged 10 years! Drive back quickly!");
    timeMachine.goToPast(barsik);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(barsik.age);
}
Console output:
Сколько лет Барсику в самом начале работы программы?
5
А теперь?
15
Елки-палки! Барсик постарел на 10 лет! Живо гони назад!
Получилось? Мы вернули коту его изначальный возраст?
5
Wow! Now the method worked differently: our cat suddenly aged, and then looked younger again! :) Let's try to figure out why. Unlike the example with primitives, in the case of objects a reference to the object is passed to the method. A reference to our original object was passed goToFuture(barsik)to the methods . Therefore, when we change inside methods , we access the very memory area where our object is stored. This is a link to the same Barsik that we created at the very beginning. This is called "passing by reference"! However, with these links everything is not so simple :) Let's try to change our example: goToPast(barsik)barsikbarsik.age

public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat = new Cat(cat.age);
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat = new Cat(cat.age);
        cat.age -= 10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        Cat barsik = new Cat(5);

        System.out.println("How old is Barsik at the very beginning of the program?");
        System.out.println(barsik.age);

        timeMachine.goToFuture(barsik);
        System.out.println("Barsik went to the future! Has his age changed?");
        System.out.println(barsik.age);

        System.out.println("And if you try in the past?");
        timeMachine.goToPast(barsik);
        System.out.println(barsik.age);
    }
}
Console output:
Сколько лет Барсику в самом начале работы программы?
5
Барсик отправился в будущее! Его возраст изменился?
5
А если попробовать в прошлое?
5
Doesn't work again! O_O Let's figure out what happened :) It's all about the methods goToPast/ goToFutureand the mechanics of how links work. Now attention!This point is the most important in understanding how links and methods work. In fact, when we call a method, goToFuture(Cat cat)it is not the object reference itself that is passed to it cat, but a copy of this reference. That is, when we pass an object to a method, there are two references to this object . This is very important for understanding what is happening. After all, this is why our last example did not change the age of the cat. In the previous example with changing the age, we simply took the passed reference inside the method goToFuture(), found the object in memory using it and changed its age ( cat.age += 10). Now inside the method goToFuture()we create a new object

(cat = new Cat(cat.age)),
and the same copy link that was passed to the method is assigned this object. As a result:
  • The first link ( Cat barsik = new Cat(5)) points to the original cat (with age 5)
  • After we passed the variable catto the method goToPast(Cat cat)and assigned it to a new object, the reference was copied.
After this, we have the final situation: two links point to two different objects. But we changed the age of only one of them - the one we created inside the method.

cat.age += 10;
And naturally, when we output it main()to the console in the method barsik.age, we see that its age has not changed. After all barsik, this is a reference variable that still points to the old, original object with age 5, to which nothing happened. All our manipulations with age were performed on a new object. Thus, it turns out that objects are passed to methods by reference. Copies of objects are never created automatically. If you passed a cat object to a method and changed its age, it will successfully change. But the values ​​of reference variables are copied when assigning and/or calling methods! Let's repeat here the paragraph about passing primitives: “When we call a method changeInt()and pass our variable there int x = 15, it is not the variable itself that gets into the method x, but its copy . After all, all the changes that happen to the copy do not affect our original variable in any way x.” With copying links, everything works exactly the same! You pass the cat object to the method. If you do something with the cat itself (that is, with the object in memory), all the changes will go through successfully - we had only one object and still have it. But if inside a method you create a new object and save it in a reference variable, which is a parameter of the method, from now on we have two objects and two reference variables. That's all! It wasn't that easy, you might even have to lecture several times. But the main thing is that you have learned this super important topic. You will often encounter arguments (even among experienced developers) about how arguments are passed in Java. Now you know exactly how it works. Keep it up! :)
Comments
  • Popular
  • New
  • Old
You must be signed in to leave a comment
This page doesn't have any comments yet