Author
John Selawsky
Senior Java Developer and Tutor at LearningTree

Methods in Java

Published in the Methods in Java group
members
Hello again! In the last lesson we got acquainted with classes and constructors, and learned how to create our own. Today we will become better acquainted with Java Methods, an essential part of classes. A Methods in Java is a set of commands which allow you to perform a specific operation in a program. In other words, a method is a function; something that your class is able to do. In other programming languages, methods are often called "functions", but in Java the word "method" is more common. :) If you remember, in the last lesson we created simple methods for a Cat class, so that our cats could say meow and jump:
public class Cat {

    String name;
    int age;

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

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

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

        smudge.sayMeow();
        smudge.jump();
    }
}
sayMeow() and jump() are methods of our class. And running these methods results in the following console output:
Meow!
Pounce!
Our methods are quite simple: they simply output text to the console. But in Java, methods have an important task: they perform actions on an object's data. They change the object's data, transform it, display it, and do other things with it. Our current methods don't do anything with the Cat object's data. Let's look at a more illustrative example:
public class Truck {

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

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
For example, here we have a class representing a Truck. The semi truck has a length, width, height, and weight (which we will need later). In the getVolume() method, we perform calculations, converting our object's data into a number representing its volume (we multiply the length, width, and height). This number will be the result of the method. Note that the method's declaration is written as public int getVolume. That means that this method must return an int. We calculated the method's return value, and now we must return it to the program that called our method. To return a method's result in Java, we use the keyword return. return volume;

Java Method Parameters

We can pass values called "arguments" to a method when calling it. A method's declaration includes a list of variables which tell us the type and order of variables that the method can accept. This list is called the "method parameters". Our Truck class's getVolume() method doesn't currently define any parameters, so let's try extending our truck example. Create a new class called BridgeOfficer. This is a police officer on duty at a bridge, who checks all passing trucks to see if their load exceeds the allowed weight.
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 checkTruck method accepts one argument, a Truck object, and determines whether or not the officer will allow the truck on the bridge. Inside the method, the logic is simple enough: if the truck's weight exceeds the maximum allowed, then the method returns false. It'll have to find another road :( If the weight is less than or equal to the maximum, it can pass, and the method returns true. If you don't fully understand the phrases "return" or "the method returns a value" yet, let's take a break from programming and consider them using a simple example from real life. :) Let's say you get sick and stay home from work for a few days. You go to the accounting department with your doctor's note, because sick leave is supposed to be paid. If we compare this situation with methods, then the accountant has a paySickLeave() method. You pass a doctor's note as an argument to this method (without it, the method won't work and you won't get paid!). Then the necessary calculations are made inside the method using your note (the accountant uses it to calculate how much the company should pay you), and the result of your work (an amount of money) is returned to you. Our program works in a similar way. It calls a method, passes data to it, and ultimately receives a result. Here's our BridgeOfficer program's main() method:
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 1! Can I go, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck 2! And can I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
We create two trucks with loads of 10,000 and 20,000. And the bridge where the officer works has a maximum weight of 15,000. The program calls the officer.checkTruck(first) method. The method calculates everything and then returns true, which the program then saves to in the boolean variable canFirstTruckGo. Now you can do whatever you want to with it (just like you can with the money the accountant gave you). At the end of the day, the code
boolean canFirstTruckGo = officer.checkTruck(first);
boils down to
boolean canFirstTruckGo =  true;
Here's a very important point: the return statement doesn't just return the method's return value, it also stops the method from running! Any code that comes after the return statement will not be executed!
public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, you're overweight!");
    } else {
        return true;
        System.out.println("Everything looks good, go ahead!");
    }
}
The officer's comments will not be displayed, because the method has already returned a result and terminated! The program returns to the place where the method was called. You don't have to watch for this: the Java compiler is smart enough to generate an error when you try to write code after a return statement.

Avengers: Parameter War

There are situations when we'll want several ways of calling a method. Why not create our own artificial intelligence? Amazon has Alexa, Apple has Siri, so why shouldn't we have one? :) In the movie Iron Man, Tony Stark creates his own incredible artificial intelligence, Jarvis. Let's pay tribute to that awesome character and name our AI in his honor. :) The first thing we need to do is to teach Jarvis to say hello to people who enter the room (it would be weird if such an amazing intellect turned out to be impolite).
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");
    }
}
Console output:
Good evening, Tony Stark. How are you?
Very good! Jarvis is now able to welcome guests. Of course, more often than not it will be his master, Tony Stark. But what if he doesn't come alone! Our sayHi() method only accepts one argument. And so it can only greet one person entering the room, and will ignore the other. Not very polite, don't you agree? :/

Java Method Overloading

In this case, we can solve the problem by simply writing 2 methods with the same name, but different parameters:
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?");
    }
}
This is called method overloading. Method overloading lets our program be more flexible and accommodate various ways of working. Let's review how it works:
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");
    }
}
Console output:
Good evening, Tony Stark. How are you?
Good evening, Tony Stark and Captain America. How are you?
Excellent, both versions worked. :) But we didn't solve the problem! What if there are three guests? We could, of course, overload the sayHi() method again, so that it accepts three guest names. But there could be 4 or 5. All the way to infinity. Isn't there a better way to teach Jarvis to handle any number of names, without overloading the sayHi() method a million times? :/ Of course there is! If there wasn't, do you think Java would 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?");
    }
}
When (String... names) is used as a parameter, it indicates that a collection of Strings will be passed to the method. We don't have to specify in advance how many there will be, so now our method is much more flexible:
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");
    }
}
Console output:
Good evening, Tony Stark. How are you?
Good evening, Captain America. How are you?
Good evening, Black Widow. How are you?
Good evening, Hulk. How are you?
Some code here will be unfamiliar to you, but don't worry about it. It's simple at its core: the method takes each name in turn and greets each guest! Plus, it will work with any number of passed strings! Two, ten, even a thousand—the method will work properly with any number of guests. Way more convenient than overloading the method for all the possibilities, don't you think? :) Here's another important point: the order of the arguments matters! Let's say our method takes a String and a number:
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!
    }
}
If the Person class's sayYourAge method takes a string and a number as inputs, then the program must pass them in that specific order! If we pass them in a different order, the compiler will generate an error and the person will not be able to say his age. By the way, constructors, which we covered in the last lesson, are also methods! You can also overload them (i.e. create several constructors with different sets of parameters) and the order of passed arguments is fundamentally important for them too. They're real methods! :)

Yet again regarding parameters

Yep, sorry, we haven't finished with them yet. :) The topic that we will study now is very important. There is a 90% chance that you will be asked about this at every future interview! Let's talk about passing arguments to methods. Consider 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 = 2018;

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

        timeMachine.goToPast(currentYear);
        System.out.println("How about now?");
        System.out.println(currentYear);
    }
}
The time machine has two methods. They both take the number representing the current year as an input, and either increase or decrease its value (depending on whether we want to go to the past or the future). But, as you can see from the console output, the method doesn't work! Console output:
What year is it?
2018
How about now?
2018
We passed the currentYear variable to the goToPast() method, but its value didn't change. We were in 2018, and here we've stayed. But why? :/ Because primitives in Java are passed to methods by value. What does that mean? When we call the goToPast() method and pass the int variable currentYear (=2018) to it, the method doesn't get the currentYear variable itself, but rather a copy of it. Of course, the value of this copy is also 2018, but any changes to the copy don't affect our original currentYear variable in any way! Let's make our code more explicit and watch 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 running!");
        System.out.println("currentYear inside the goToPast method (at the beginning) = " + currentYear);
        currentYear = currentYear-10;
        System.out.println("currentYear inside the goToPast method (at the end) = " + currentYear);
    }

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

        System.out.println("What was the year when the program started?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And what year is it now?");
        System.out.println(currentYear);
    }
}
Console output:
What was the year when the program started?
2018
The goToPast method has started running!
currentYear inside the goToPast method (at the beginning) = 2018
currentYear inside the goToPast method (at the end) = 2008
And what year is it now?
2018
This clearly shows that the variable passed to the goToPast() method is only a copy of currentYear. And changing the copy doesn't affect the "original" value. "Pass by reference" means the exact opposite. Let's practice on cats! I mean, let's see what passing by reference looks like using a cat example. :)
public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
Now with the help of our time machine we'll send Smudge, the world's first time-traveling cat, into the past and the future! Let's modify the TimeMachine class so that it works with Cat objects;
public class TimeMachine {

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

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }
}
Now the methods don't just change the passed number. Rather, they change that specific Cat's age field. You'll recall that this didn't work for us with primitives, because the original number didn't change. Let's see what will happen!
public static void main(String[] args) {

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

    System.out.println("How old was Smudge when the program started?");
    System.out.println(smudge.age);

    timeMachine.goToFuture(smudge);
    System.out.println("How about now?");
    System.out.println(smudge.age);

    System.out.println("Holy smokes! Smudge has aged 10 years! Back up quickly!");
    timeMachine.goToPast(smudge);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(smudge.age);
}
Console output:
How old was Smudge when the program started running?
5
How about now?
15
Holy smokes! Smudge has aged 10 years! Back up quickly!
Did it work? Have we returned the cat to its original age?
5
Wow! Now the method did something different: our cat aged drastically, but then it got young again! :) Let's try to figure out why. Unlike the example with primitives, when objects are passed to a method they are passed by reference. A reference to the original smudge object was passed to the changeAge() method. So, when we change smudge.age inside the method, we're referencing the same area of memory where our object is stored. It's a reference to the same Smudge that we created initially. This is called "passing by reference"! However, not everything with references is that easy. :) Let's try changing our example:
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 smudge = new Cat(5);

        System.out.println("How old was Smudge when the program started?");
        System.out.println(smudge.age);

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

        System.out.println ("And if you try going back?");
        timeMachine.goToPast(smudge);
        System.out.println(smudge.age);
    }
}
Console output:
How old was Smudge when the program started running?
5
Smudge went to the future! Has his age changed?
5
And if you try going back?
5
It doesn't work again! О_О Let's figure out what happened. :) It has everything to do with the goToPast/goToFuture methods and how references work. Now, your attention, please! This is the most important thing to understand about how references and methods work. The fact is, when we call the goToFuture(Cat cat) method, it's a copy of the reference to the cat object that gets passed, not the reference itself. Thus, when we pass an object to a method, there are two references to the object. This is very important for understanding what's happening. This is precisely why the cat's age didn't change in our last example. In the previous example, when changing the age, we simply took the reference passed to the goToFuture() method, and used it to find the object in memory and change its age (cat.age += 10). But now, inside the goToFuture() method, we're creating a new object (cat = new Cat(cat.age)), and this object is assigned the same reference copy that was passed to the method. As a result:
  • The first reference (Cat smudge = new Cat (5)) points to the original cat (with age 5)
  • After that, when we passed the cat variable the goToPast() method and assigned it a new object, the reference was copied.
And this brought us to the final outcome: two references pointing to two different objects. But we only changed the age of one of them (the one created inside the method).
cat.age += 10;
And of course, in the main() method we can see on the console that the cat's age, smudge.age , has not changed. After all, smudge is a reference variable that still points to the old, original object with age 5, and we didn't do anything with that object. All our age changes were performed on the new object. So, it turns out that objects are passed to methods by reference. Copies of objects are never created automatically. If you pass a cat object to a method and change its age, you will change its age. But reference variables are copied when assigning values and/or calling methods! Let's repeat here what we said about passing primitives: "When we call the changeInt() method and pass the int variable x (=15), the method doesn't get the x variable itself, but rather a copy of it. Therefore, any changes made to the copy don't affect our original x variable in any way." When copying references, everything works exactly the same way! You pass the cat object to the method. If you do something to the cat itself (that is, with the object in memory), all your changes will be successfully applied, since we only had one object and still have only one object. But, if you create a new object inside the method and assign it to the reference variable passed to the method as an argument, you'll just be assigning the new object to a copy of the reference variable. From that moment on, we'll have two objects and two reference variables. That's it! That wasn't so easy. You might even have had to read the lesson several times. But, the important thing is that you've mastered this super-important topic. You'll still end up arguing more than once about how arguments are passed in Java (even among experienced developers). But, now you know exactly how it works. Keep it up! :) To reinforce what you learned, we suggest you watch a video lesson from our Java Course

More reading:

Comments (138)
  • Popular
  • New
  • Old
You must be signed in to leave a comment
Pekotski
Level 16 , Zurich, Switzerland
1 February, 15:50
Mastery in tedious explanation, missing important points. I think at point when moving from primitive values to objects (cat) - the author also got lost. That's what happens when developers play educators. Learn some basics of humane communication dude!
NightroWave
Level 3 , San Francisco, Norway
20 September 2023, 18:12
Too long and tedious to understand just by reading all this text. The result: you end up exhausted without any idea of what you were here for.
Lorena Vargas
Level 4 , Mexico
8 July 2023, 00:48
Hi, someone can explain to me, why the second example of TimeMachine it works if is the same that the last example only with more explanation? please :) what is the difference?
Beastenjahrn
Level 11 , Germany, Germany
5 August 2023, 18:15
It doesn't work. The currentYear in the main-method don't change. It's still 2018. The variable currentYear in the goToPast-method has change in both example. At the start it's 2018. Then "currentYear = currentYear-10;" change the value to 2008 (only) for the goToPast-method so it's 2008. The different between both example is only that in the second example in goToPast-method currentYear is print on the screen.
Muganzi Elwin
Level 48 , Kampala, Uganda
Expert
2 June 2023, 11:18
For sure, it wasn't so easy. I had to read the lesson several times. Am still wondering even if I have got the concept. Nevertheless, thanks so much.
Serhii Matviienko
Level 21 , Ukraine, Ukraine
Expert
24 August 2023, 08:51
I have to say it will be easier to understand if you try the code by yourself 😉
Anonymous #11274698
Level 8 , Gorzow Wielkopolski, Poland
15 May 2023, 12:04
public class Jarvis { public void sayHi(String...names) { for (String name: names) { System.out.println("Good evening, " + name + ". How are you?"); } } How does it work if "for" work with 3 arguments? Example: for(int a=0; a<1; a++)
Edariel
Level 3 , Praha, Czech Repuclic
2 November 2023, 17:10
It's 'for each'.
David
Level 6 , Spain
15 March 2023, 20:19
Perfecto, mejor explicado imposible. Gracias!!!
Hoist
Level 32 , San Diego, United States
25 January 2023, 03:21
FUNDAMENTAL TOPIC: 1) Watch the Method VIDEO top to bottom and understand single every step ! Yikes: At 10:06 the new example Methods details get covered up off the screen so you can't see WHY the output is why it is ... )) At 10:26 the Something and Example methods drop off the screen to see .... which makes this hard to follow ! Call Stack fun begins at 13:00 ! It's great )) Read this thread over and over ..
manny9876
Level 34 , Israel
2 November 2022, 18:42
Amazing! I'll have to reread this a few more times to get it down well, but the article is well-written, exciting, and fun! Thanks!
为何而活liker
Level 3 , China, China
2 September 2022, 01:56
difficult to understand as not in Chinese.
KAI
Level 22 , Wenzhou, China
26 February 2023, 09:46
用翻译软件
悯琁
Level 3 , Guangzhou, China
day before yesterday, 01:40
微软自带翻译吧,man
NeoBTK
Level 8 , Katowice, Poland
28 August 2022, 16:33
I changed it a little bit, so it may be more clear for some people:
Cat smudge = new Cat(5);   // this is cat1
.
.
.
    public void goToFuture(Cat cat1) {
        cat2 = new Cat(cat1.age);   // cat2 gets the same age from cat1
        cat2.age += 10;
    }

    public void goToPast(Cat cat1) {
        cat2= new Cat(cat1.age);   // cat2 gets the same age from cat1
        cat2.age -= 10;
    }

}
悯琁
Level 3 , Guangzhou, China
day before yesterday, 01:41
确实是这么理解的,man