Skip to main content
Logo image

Section 3.1 Writing methods

Writing Java code consists of about equal parts writing methods and using them but it is probably easier to understand how to use them if we understand what they are so we’ll start by looking at how to write our own methods. In the next lesson we’ll look at a bunch of methods that are part of Java that we don’t have to write but which we can use.

Subsection 3.1.1 Methods signatures

As we learned in the previous unit, to create a variable we need to declare it, specify its name and its type, and optionally provide an initial value. Declaring methods is similar but there are more parts we need to specify.
Like a variable, a method has a name which we will use to call it. Additionally a method has a return type which specifies the kind of value (if any) the method returns when called. And a method can take any number of arguments, values it can use in its computation. To specify what number and types of arguments it needs, a method defines parameters which are variables that are declared as part of the method and which hold the argument values when the method is called. Together all these piecesβ€”the name, the return type and the parametersβ€”make up the method signature or method header.
A complete method signature for a method that adds two numbers and returns the result might look something like this:
public static int add(int a, int b)
For now don’t worry about the public static, just treat that as boiler plate that all your methods will start with for now. (We’ll start writing methods without static in ChapterΒ 8Β Classes.) The next word, int, is the return type. It is the name of a type or the special keyword void which means the method doesn’t return any value. Then comes the name of the method, in this case, add. And finally, in parentheses, the method’s parameter list, a comma-delimited list of variables which are the method’s parameters. Parameters are declared like other variables with a type and a name. In this method there are two, named a and b, both of type int.
The signature of method that doesn’t return a value but which has some side effects such drawing a square on the screen might look like this:
public static void drawSquare(int x, int y, int width, int height)

Subsection 3.1.2 Method calls

The point of a method signature is that it gives us all the information we need to call the method. A method call consists of the method name followed by an argument list, a list of expressions separated by commas and enclosed in parentheses ().
The number of expressions in the argument list has to match the number of parameters in the parameter list in the method signature. And each expression must evaluate to a value of the correct data type for the corresponding parameter. But the expressions can be anything: variables, literals, or any other expressions that evaluate to the correct types. The values of the expressions in the argument list become the values of the method’s parameters when the method’s code runs.
If a method takes no arguments, i.e. has an empty parameter list, there will be nothing between the parentheses but the parentheses are still needed so Java knows we are calling a method and not referring to a variable.
For instance, a call to the add method with the signature above might look like this: add(10, 20).
When a method, such as add, has a return type other than void we can use the method call as an expression whose value will be whatever value the method returns. In this case that means we can use a call to add anywhere we need a value of type int. For example, we can use it to provide the initial value in a variable declaration:
int sum = add(10, 20);

Subsection 3.1.3 Method bodies

Of course the signature does not tell us everything about the method. In particular, it does not tell us what computation the method actually performs or how it does it. For that we need to write a method body. The body is enclosed in a pair of curly braces ({}) and contains code that can use the variables from the parameter list. And at any point in the method body we can use the keyword return followed by an expression to cause the method to return the value of that expression as the value of the method call.
For instance, adding the body to our add method to get a complete method definition would look like this:
public static int add(int a, int b) {
  return a + b;
}
Seeing the method body, we can actually understand exactly what happens in a line like:
int sum = add(10, 20);
When Java hits the call to add, it first creates variables corresponding to the parameters a and b and initializes them with the argument values 10 and 20. Then it executes the body of the method until it hits a return at which point it evaluates the expression after the return and makes that value the value of the method call. In other words, roughly equivalent to this.
int a = 10;
int b = 20;
int sum = a + b;
The main difference is that when we call add, the variables a and b only exist within the method. Outside of the body of the method we can’t refer to them.

Activity 3.1.1. Trace call to add.

To see how a method call works click on the next button below the code to step through the code and watch the red arrow jump to the method that is being run and watch how the arguments are passed into the parameter variables and how the returned value comes back to where the method was called.

Subsection 3.1.4 Making smaller methods

The main purpose of methods is to break a program up into smaller chunks that are easier to think about. That also often results in removing duplicated code which also helps reduce the overall complexity of our code. All other things being equal, less code is better than more code.
For example, the song β€œOld MacDonald Had a Farm”, like many children’s songs, has a lot of repetition. If we wanted to write a program to print out the song’s lyrics, we could write out a bunch of calls to println as shown below. But then our code would have a lot of duplicate codeβ€”the same lines of code occurring in multiple places. See if you can identify the duplicate code in the following implementation of such a program.

Activity 3.1.2. Finding duplicate code.

Click on all the lines that are exactly the same as another line.
Look for lines that are completely identical.
public static void main(String args[]) {
    System.out.println("Old MacDonald had a farm,");
    System.out.println("E-I-E-I-O");
    System.out.println("And on this farm, they had a cow.");
    System.out.println("E-I-E-I-O");
    System.out.println("With a moo moo here and a moo moo there");
    System.out.println("Here a moo, there a moo, everywhere a moo moo");
    System.out.println("Old MacDonald had a farm,");
    System.out.println("E-I-E-I-O");
}
Did you find some repeated lines? You may have noticed that the first two lines are repeated. When you see repeated code, that is a signal to make a new method!
The code tracing activity below shows how a song can be divided up into methods. Click on the β€œNext” button below the code to step through the code and watch the red arrow jump to the method that is being run.
Execution in Java always begins in the main method in the current class. Then, the flow of control skips from method to method as they are called. Notice that when a method ends, it returns to where the method was called. The main method below calls the intro method which prints a line and then calls the chorus method. The code in chorus prints one line and then returns back to intro which is then done so it returns to main which then executes the next line.

Activity 3.1.3. Old MacDonald with methods.

Click on the next button below the code to step through the code and watch the red arrow jump to the method that is being run.
Just like variable names, method names should be chosen to be meaningful and to describe what the method does. Methods can be defined in any order, but usually programmers put the main method at the end the class after all the methods that it uses are defined.
Try writing your own method calls below to add another verse to the song.

Activity 3.1.4. Add an animal.

Scroll down to the main method below and add lines of code to the main method for the second verse of the Old MacDonald Song by calling the intro() and chorus() methods and printing out lines about a duck or another animal.

Activity 3.1.5. Mental execution.

Figuring out what the code does is called code tracing or mental execution. You can use a tool like the visualizer we used above to step through code but it’s important to develop the skill of mentally executing code to determine what it does. Start at the main method and then follow each method call to see what happens.
public class Song {
    public static void print() {
        System.out.print("I like to ");
        eat();
        eat();
        eat();
        fruit();
    }

    public static void fruit() {
        System.out.println("apples and bananas!");
    }

    public static void eat() {
        System.out.print("eat ");
    }

    public static void main(String[] args) {
        print();
    }
}
  • I like to eat eat eat.
  • Try tracing through the print method and see what happens when it calls the other methods.
  • I like to eat eat eat fruit.
  • There is a fruit() method but it does not print out the word fruit.
  • I like to apples and bananas eat.
  • The order things are printed out depends on the order in which they are called from the print method.
  • I like to eat eat eat apples and bananas!
  • Yes, the print method calls the eat method 3 times and then the fruit method to print this.
  • Nothing, it does not compile.
  • Try the code in an active code window to see that it does work.

Subsection 3.1.5 Removing even more duplication

Let’s take another look at the Old MacDonald Song and see if we can remove even more duplication by writing a with that takes arguments. To start, do this activity to find some lines of code that are not identical but are quite similar.

Activity 3.1.6. Duplication with small differences.

Did you find the lines that are identical except for the animal name and the sound that they make? It would be nice if we could write a method to print those lines that captures the common pattern but fills in the specifics for each animal. That’s what method arguments are for.
Whereas the chorus and eieio methods always print exactly the same thing, if we want to write a method verse that prints one verse, we need to write a method that takes arguments and prints something different based on those arguments. And the differences you identified between the similar lines in the code above can point us to the arguments we need to pass.
Here’s one way to write a verse method with two parameters, animal and sound.
/* This method prints out a verse for any given animal and sound.
   @param animal - the name of the animal
   @param sound - the sound the animal makes
*/
public static void verse(String animal, String sound) {
    System.out.println("And on this farm, they had a " + animal);
    eieio();
    System.out.println("With a " + sound + " " + sound +
                       " here and a " + sound + " " + sound + " there");
    System.out.println("Here a " + sound + ", there a " + sound +
                       ", everywhere a " + sound + " " + sound);
}
With this method, the main method can now just consist of calls to the chorus and verse methods, showing clearly the structure of the song in terms that might make sense to a musician. This is a common effect of creating good abstractions: while the detailsβ€”in this case of what exactly is printedβ€”are hidden, the higher-level structure is much easier to see.
public static void main(String[] args) {
    chorus();
    verse("cow", "moo");
    chorus();
    verse("duck", "quack");
    chorus();
}
When a method like verse is called, the method definition is found by finding a method whose signature matches the call, meaning the name matches and the number and declared type of the parameters are compatible with the number and types of the argument expressions.
Here’s what that looks like for two calls to verse above. The arguments "cow" and "moo" or "duck" and "quack" are matched up with the parameters animal and sound.
Arguments to Parameters
Figure 3.1.1. Matching Arguments to Parameters
Java uses call by value when it passes arguments to methods. This means that a copy of the value in the argument is saved in the parameter variable. Call by value initializes the parameters with copies of the arguments. If the parameter variable changes its value inside the method, the original value outside the method is not changed.

Activity 3.1.7. Trace verse calls.

Click on the β€œNext” button below the code to step through the code. This time in addition to watch the red arrow jump to the method that is being run, pay attention to how the arguments in the calls to verse become the values of the parameters.

Activity 3.1.8. Add more animals.

Let’s add more animals to the farm! Scroll down to the main method, and add another verse with the animal β€œgoose” and the sound β€œhonk” by calling the verse method with the appropriate arguments. Then call chorus again. Then add another animal and sound of your choice.

Subsection 3.1.6 Coding Challenge: Song with Parameters

Here’s another song, The Ants Go Marching with a repetitive structure. The verses below have a lot of repeated words and phrases. Click on the words or phrases that are different in each verse. These will be the arguments that you will pass to the methods in your song code.

Activity 3.1.9. The Ants Go Marching.

Project 3.1.10. Implement ants song.

Write code in the main method that calls the verse method to print out all three verses for the Ants Go Marching song above.

Subsection 3.1.7 Non-void methods

Most of the methods we have written so far have been void methods which do not return a value but are called for their side effects. However, many methods act like mathematical functions that calculate and return a value based on their arguments.
Since these methods all have some actual return type, not void they are called non-void methods. You can imagine a non-void method as a calculating machine that takes numbers as arguments and returns a calculated result or like a toaster that takes bread as an input and returns toast.
function
Figure 3.1.2. Method that takes arguments and returns a value
The add method we used as an example was a non-void method. Here’s another one.
Square Method
Figure 3.1.3. The Square Method
Here is a simple implementation of this method which takes an int number as an argument, squares that number, and returns the result. Notice that instead of static void, the header includes static int to indicate that the method returns an integer value.
public static int square(int number) {
    return number * number;
}
The return statement is used to return a value from the method back to the calling code. The return value must be the same type as the return type in the method header. The return statement also ends the method execution, so any code after the return statement is not executed. Let’s try this below. Click on the next button to step through the code in the visualization below and see the variables and the return values.

Activity 3.1.11. Trace square.

Click on the next button below the code to step through the code and watch the red arrow jump to the method that is being run and watch how the argument is passed into the parameter variable and the return value.
When calling the square method, the return value can be stored in a variable or used as part of an expression. In the main method above, the variable y is assigned the return value of the first call to the square method. When a call to square is used in an argument list, such as in the second call to System.out.println, the return value becomes the argument to the method being called.
// Saving the returned value of the square method in a variable
int y = square(5);
System.out.println(y); // prints 25
// Printing the returned value of the square method directly
System.out.println(square(4)); // prints 16

Activity 3.1.12. Call square.

Add another call to the square method in the main method that prints out the square of 6.

Activity 3.1.13. Mental execution.

What does the following code print out?
public class MethodTrace {
    public static int square(int x) {
        return x * x;
    }

    public static int divide(int x, int y) {
        return x / y;
    }

    public static void main(String[] args) {
        System.out.println(square(3) + divide(5,2));
    }
}
  • Yes, the square(3) method is called first and returns 9. Then the divide(5,2) method is called and returns 2 because it does int division and leaves off the decimal part. The sum of 9 and 2 is 11.
  • The divide function does integer division.
  • The + here will be interpreted as addition since the methods return ints.
  • square(3)+divide(5,2)
  • The square and divide methods are called and return values that are added together.
  • Nothing, it does not compile.
  • Try the code in an active code window.

Subsection 3.1.8 Common errors with non-void methods

A common error with non-void methods is forgetting to do something with the value returned from a method. When you call a method that returns a value, you should do something with that value like assigning it to a variable or printing it out. To use the return value when calling a non- void method, it must be stored in a variable or used as part of an expression.
Another common error is a mismatch in types or order for the arguments or return values. For example, if a method returns a double value, you cannot assign it to an int variable.

Activity 3.1.14. Fix type errors.

Fix the method calls below in the main method. Make sure the number and types of the arguments match what the methods expect. And check that the variables the returned values are assigned to are of the right types. Do not change the methods other than main.

Subsection 3.1.9 Summary

  • (AP 1.9.A.1) A method is a named block of code that only runs when it is called. A block of code is any section of code that is enclosed in braces.
  • (AP 1.9.A.1) Procedural abstraction allows a programmer to use a method by knowing what the method does even if they do not know how the method was written.
  • (AP 1.9.B.5) A method call interrupts the sequential execution of statements, causing the program to first execute the statements in the method before continuing. Once the last statement in the method has been executed or a return statement is executed, the flow of control is returned to the point immediately following where the method was called.
  • (AP 1.9.A.2) A parameter is a variable declared in the header of a method or constructor and can be used inside the body of the method. This allows values or arguments to be passed and used by a method or constructor.
  • (AP 1.9.A.2) A method signature for a method with parameters consists of the method name and the ordered list of parameter types. A method signature for a method without parameters consists of the method name and an empty parameter list.
  • (AP 1.9.B.3) An argument is a value that is passed into a method when the method is called. The arguments passed to a method must be compatible in number and order with the types identified in the parameter list of the method signature. When calling methods, arguments are passed using call by value.
  • (AP 1.9.B.3) Call by value initializes the parameters with copies of the arguments.
  • (AP 1.9.B.4) Methods are said to be overloaded when there are multiple methods with the same name but different signatures.
  • (AP 1.10.A.1) Class methods are associated with the class (not instances of the class which we will see in later lessons).
  • (AP 1.10.A.2) Class methods include the keyword static in the header before the method name.
  • (AP 1.9.B.1) A void method does not have a return value and is therefore not called as part of an expression.
  • (AP 1.9.B.2) A non-void method returns a value that is the same type as the return type in the header.
  • (AP 1.9.B.2) To use the return value when calling a non-void method, it must be stored in a variable or used as part of an expression.
  • Common errors with methods are mismatches in the order or type of arguments, return values, and forgetting to do something with the value returned from a method. When you call a method that returns a value, you should do something with that value like assigning it to a variable or printing it out.

Subsection 3.1.10 AP Practice

Activity 3.1.15. Mental execution.

Consider the following class definition.
public class Cat
{
    public static void sound1()
    {
        System.out.print("meow ");
    }

    public static void sound2()
    {
        System.out.print("purr ");
    }

    public static void hello()
    {
        sound2();
        sound1();
    }
}
Which of the following code segments, if located in a method inside the Cat class, will cause the message β€œpurr meow purr” to be printed?
  • hello();
    
  • This would print β€œpurr meow β€œ
  • hello();
    sound2();
    
  • Correct!
  • sound1()
    sound2();
    sound1();
    
  • This would print out β€œmeow purr meow” instead of β€œpurr meow purr”.
  • purr();
    meow();
    purr()
    
  • This would cause a syntax error since those are not the names of the methods.

Activity 3.1.16. Calculate pizza boxes.

Consider the following method.
public static double calculatePizzaBoxes(int numOfPeople, double slicesPerBox)
{ /*implementation not shown */}
Which of the following lines of code, if located in a method in the same class as calculatePizzaBoxes, will compile without an error?
  • int result = calculatePizzaBoxes(45, 9.0);
  • The method calculatePizzaBoxes returns a double value that cannot be saved into an int variable.
  • double result = calculatePizzaBoxes(45.0, 9.0);
  • The method calculatePizzaBoxes has an int parameter that cannot hold a double value 45.0.
  • int result = calculatePizzaBoxes(45.0, 9);
  • The method calculatePizzaBoxes has an int parameter that cannot hold a double value 45.0. Note that the int 9 can be passed into a double parameter.
  • double result = calculatePizzaBoxes(45, 9.0);
  • The method calculatePizzaBoxes has an int and a double parameter and returns a double result.
  • result = calculatePizzaBoxes(45, 9);
  • The variable result has not been declared (with an appropriate data type).

Activity 3.1.17. Inches to centimeters.

Consider the following methods:
public void static inchesToCentimeters(double i)
{
    double c = i * 2.54;
    printInCentimeters(i, c);
}

public void static printInCentimeters(double inches, double centimeters)
{
    System.out.print(inches + "-->" + centimeters);
}
Assume that the method call inchesToCentimeters(10) appears in a static method in the same class. What is printed as a result of the method call?
  • inches –> centimeters
  • The values of the variables inches and centimeters should be printed out, not the words.
  • 10 –> 25
  • Two doubles should be printed, not two ints, and the centimeters should be 25.4
  • 25.4 –> 10
  • Inches should be printed before centimeters.
  • 10 –> 12.54
  • c = 10 * 2.54 = 25.4, not 12.54.
  • 10.0 –> 25.4
  • Correct! centimeters = 10 * 2.54 = 25.4.
You have attempted of activities on this page.