User Oleksandr Miadelets
Oleksandr Miadelets
Head of Developers Team at CodeGym

Method declaration

Published in the Java Developer group
Hi! You've already known about creating your own classes with fields and methods. Now we'll dwell on methods.
Method declaration - 1
Of course, we've already done this more than once in our lessons, but we've mainly covered generalities. Today, we're going to dissect methods, and study what they're made of, the various ways to create them, and how to manage it all. :) Let's go!

Method declaration

All the code that defines a method is called a method declaration. The general form of a method declaration can be described as follows:

access modifier, return type, method name (parameter list) {
    // method body
}
As examples, take a look at the declarations of the various methods of the Dog class.

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. Access modifier

The access modifier is always indicated first. All of the Dog class's methods are marked with the public modifier. This means we can call them from any other class:

public class Main {

   public static void main(String[] args) {

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

}
As you can see, the Dog class's methods are easily accessed in the Main class. This is possible due to the public modifier. In Java, there are other modifiers. They don't all allow methods to be used in other classes. We'll talk about them in other lessons. The main thing to remember is what the modifier is responsible for: whether a method is accessible in other classes :)

2. static keyword

One of the Dog methods, main(), is marked with the keyword static. It's also part of the method declaration, and we already know its meaning. We didn't mention it in the method declaration template given at the beginning of the lesson, because it is optional. If it is specified, then it must come after the access modifier. Remember that in recent lessons we talked about static (class) variables? When applied to methods, this keyword has roughly the same meaning. If a method is static, then it can be used without a reference to a specific object of the class. And indeed, you don't need a Dog object to run the static main() method in the Dog class. It will run just fine without one. If this method were not static, then we would first need to create an object in order to run it.

3. Return value

If our method should return something, then we specify the type of the return value. This is evident from the example of the getName() getter:

public String getName() {
   return name;
}
It returns a String object. If a method doesn't return anything, then keyword void is used instead, as in the woof() method:

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

Methods with the same name

There are situations when we'll want several different ways to call 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 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 it will be his master, Tony Stark. But what if he doesn't come alone! But 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, agreed? :/ 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 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");
   }
}
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? Inside the method, we iterate over all the arguments and display phrases formatted with names. Here we use a simplified for-each loop (which you've seen before). It's perfect here, because the (String... names) notation actually means that the compiler puts all the passed arguments into an array. As a result, we can work with variable names as we would work with an array, including by iterating through it in a loop. 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 example of method overloading. Let's give Jarvis a printInfoFromDatabase() method. It will display information about a person from a database. If the database indicates that a person is a superhero or supervillain, we'll display that information:

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");
   }
}
Output: Laura Palmer. Date of birth: July 22, 1972. Twin Peaks, Washington Max Eisenhardt. Height: 15.6 ft. Weight: 189 lbs. Also known as the supervillain Magneto So, our method's behavior depends on the data that we pass to it. 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 input, then this is the order that these arguments must be passed to the method! If we pass them in a different order, then the compiler will generate an error and the person won't 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! :)

How to invoke methods with similar parameters

As you know, null is a keyword in Java. It's very important to understand that null is neither an object nor a data type. Imagine that we have a Person class and an introduce() method, which announces the person's name and age. Furthermore, the age can be passed as text or a number.

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);
   }
}
We're already familiar with overloading, so we know that both methods will behavior as they should: My name is Alex. My age is twenty-one My name is Mary. My age is 32 But what will happen if we pass null as the second parameter instead of a string or a number?

public static void main(String[] args) {

   Person victor = new Person();
   victor.introduce("Victor", null);// Ambiguous method call!
}
We will get a compilation error! What causes this and what exactly is the "ambiguity"? In fact, it's all very simple. The problem is that we have two versions of the method: one with a String as the second argument, and one with an Integer as the second argument. But a String and an Integer can both be null! Because they are reference types, null is the default value for both of them. That's why in this situation the compiler can't figure out which version of the method it should call. The solution to this problem is quite simple. Null can be explicitly converted to a specific reference type. Thus, when you call a method, you can indicate in parentheses the data type you want for the second argument! The compiler will understand your "hint" and will call the correct method:

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);
   }
}
Output: Method with two strings! My name is Victor. My age is null Note that if the number parameter were a primitive int, rather than an instance of the Integer reference type, there wouldn't have been such an error.

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);
   }
}
Can you guess why? If you did guess why, well done! :) Because primitives can't be null. Now the compiler has only one choice, i.e. to call the introduce() method with two strings. This is the version of the method that will run every time the method is called.

More reading:

Comments (44)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
To be brave #10900452 Level 14, Пекин, United States
13 January 2022
int类型的变量,初始化后,值为0
Andy Lee Level 10
20 March 2021
explicit
Andrei Level 41
12 November 2020
It is still not entirely clear for me, how the static keyword works. We have the following sentence which applies to the code after it: "When applied to methods, this keyword has roughly the same meaning. If a method is static, then it can be used without a reference to a specific object of the class. And indeed, you don't need a Dog object to run the static main() method in the Dog class. It will run just fine without one. If this method were not static, then we would first need to create an object in order to run it. "

public class Main {

   public static void main(String[] args) {

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

}
It is not clear to me what it is meant by: "If this method were not static, then we would first need to create an object in order to run it. " Can someone please give more details? :-/
Banak Level 29, Saint-Gratien, France
5 November 2020
super
wangshijie Level 11, Xinzhou, China
7 August 2020
This article is easy to understand and worth learning and thinking.
Peter Schrijver Level 23, Hilversum, Netherlands
8 June 2020
Very useful information
Austeja Level 10, Kaunas, Lithuania
30 April 2020
This really explains static methods better than before. Or maybe it is just clearer because I am lvl9 now (not 4)? Very good and informative piece of info!
Larisa Alexa Level 20, Iasi, Romania
21 April 2020
I have a complicated relationship with methods. This article should have been introduced much earlier! please consider
Ashish RajAnand Level 13, Bhilai , India
18 April 2020
nice i love it
王诗凯 Level 23, Redwood City, United States
8 April 2020
It makes me fully understand how static works in program!