5.1. Writing Methods¶
Up until this unit, you wrote all code in the main method, but now you will be creating new methods that can be called by the main method. Why have multiple methods instead of just one? Procedural Abstraction allows us to name a block of code as a method and call it whenever we need it, abstracting away the details of how it works. This serves to organize our code by function and reduce the repetition of code. In addition, it helps with debugging and maintenance since changes to that block of code only need to happen in one place. Here are some of the main reasons to use multiple methods in your programs:
Reducing Complexity: Divide a problem into subproblems to solve it a piece at a time.
Reusing Code: Avoid repetition of code.
Maintainability and Debugging: Smaller methods are easier to debug and understand.
Let’s look at an example with repetition and then we will create a method to reduce the redundant code.
public static void main(String args[]) { System.out.println("I'm looking over a four-leaf clover"); System.out.println("That I overlooked before"); System.out.println("One leaf is sunshine, the second is rain"); System.out.println("Third is the roses that grow in the lane"); System.out.println(); System.out.println("No need explaining, the one remaining"); System.out.println("Is somebody I adore"); System.out.println("I'm looking over a four-leaf clover"); System.out.println("That I overlooked before"); }
The two-line chorus is repeated at the beginning and ending of the song.
When you see duplicate lines of code, that is a signal for you to make a new method! A method is a named set of statements. When we want to execute the statements, we call the method using its name. In a subsequent lesson you will create methods that are called using an object, referred to as instance methods or object methods. The methods in this unit are called without an object, so they are static methods. Static methods are also referred to as class methods.
Note
static methods - can call without an object m()
instance methods - must call using an object obj.m()
5.1.1. Writing Static Methods¶
There are two steps to writing and using a static method:
Step 1. Method Definition
Step 2. Method Call
You define a method by writing the method’s header and body. The header is also called a method signature. The parts of the main method header are shown in the figure below, which include an access modifier, static modifier, return type, name, and formal parameters. The method body consists of a set of statements enclosed in curly braces { }.
- public
- This is the access modifier.
- static
- This is the non-access modifier.
- void
- This is the return type.
- main
- Correct.
5-1-2: Given the method signature, what is the method name?
The code below contains a chorus() method definition that we could write to encapsulate the two lines that get repeated in the song.
// Step 1: define a new method named chorus
public static void chorus()
{
System.out.println("I'm looking over a four-leaf clover");
System.out.println("That I overlooked before");
}
Whenever you want to use a method, you call it using the method name followed by parentheses.
The method header public static void chorus()
indicates the return type is void and there are no formal parameters
between the parentheses, which means you can call the method as shown:
// Step 2: call the chorus method
chorus();
Notice that we can just call the static method, we don’t need to create an object to use for calling the method. The main method can call the chorus method multiple times to repeat the two lines of the song.
Run the following code to see the song print out.
Notice the first line of code in the main method
is a call to the new method chorus()
.
Can you replace the last two print statements in the main
method with another call to the chorus()
method?
Use the CodeLens to step through the program and notice what happens when the main method calls the chorus method.
public class GreetingExample { public static void greet() { System.out.println("Hello!"); System.out.println("How are you?"); } public static void main(String[] args) { System.out.println("Before greeting"); greet(); System.out.println("After greeting"); } }
public class GreetingExample { public static void greet() { System.out.println("Hello!"); System.out.println("How are you?"); } public static void main(String[] args) { System.out.println("Before greeting"); greet(); System.out.println("After greeting"); } }
public class GreetingExample { public static void greet() { System.out.println("Hello!"); System.out.println("How are you?"); } public static void main(String[] args) { System.out.println("Before greeting"); greet(); System.out.println("After greeting"); } }
5.1.2. Flow of Execution - Stack Diagrams¶
A class can contain several methods. It can be tempting to think the methods are executed in the order they appear in the class, but this is not the case.
A program always begins at the first statement in the main method. Each statement in the main is executed one at a time until you reach a method call. A method call causes the program execution to jump to the first line of the called method. Each statement in the called method is then executed in order. When the called method is done, the program returns back to the main method.
How does the program keep track of all of this? The Java runtime environment keeps track of the method calls using a call stack. The call stack is made up of stack frames. Each time a method is called, a new frame is created and added to the stack. A frame contains the method’s parameters and local variables, along with the number of the current line that is about to be executed.
The CodeLens Visualizer represents the call stack using a stack diagram, with each method frame drawn as a box. When a method is called, a new frame is added to the bottom of the stack diagram. You can tell which method is currently executing by looking at the bottom of the stack.
Click on each tab to observe the flow of control for the GreetingExample
class.
The program starts at the first line of the main method. The red arrow shows that line 11 is next to execute.
The stack diagram is in the right portion of the screen print, below the print output section
where it says “Frames”. There is a single frame for the main method main:11
,
indicating line 11 is the current line in the method.
Click on the next tab to see what happens after line 11 executes.
The red arrow shows that line 12 is next to execute.
The main method frame main:12
is updated to indicate the current line.
Click on the next tab to see what happens when line 12 executes and the greet() method is called.
Control is transferred into the greet() method.
The stack diagram shows a new frame was created for the greet() method greet:5
, indicating
line 5 is the current line in the method.
Note that the CodeLens tool adds the new method frame to the bottom of the stack diagram.
The output is updated after line 5 is executed. The greet:6
frame indicates line 6 is next to execute.
The output is updated after line 6 is executed. The greet:7
frame indicates line 7 is next to execute, which is the last line of code in the method.
When line 7 executes, the greet() method will return to the previous frame in the stack, which is the main method.
But how does the program know which line in the main to return to?
The method frame main:12
indicates that control should return to line 12.
The greet() method completed and its frame was removed from the stack.
Control returned to the main method and since there was nothing else to do on line 12, the
program moves forward to line 13 as depicted in the method frame main:13
. The program
will execute the remaining lines of code in the main method and then terminate.
You can step through the program using the GreetingExample Visualizer.
- apples and bananas! eat I like to.
- Try tracing through the main method and see what happens when it calls the other methods.
- I like to consume consume consume fruit.
- The consume() method does not print the word consume, and the fruit() method but it does not print the word fruit.
- I like to apples and bananas! eat.
- Try tracing through the main method and see what happens when it calls the other methods.
- I like to eat eat eat apples and bananas!
- Yes, the print method calls the consume method 3 times and then the fruit method to print this.
5-1-8: What does the following code print?
public class LikeFood
{
public static void fruit()
{
System.out.println("apples and bananas!");
}
public static void consume()
{
System.out.print("eat ");
}
public static void main(String[] args)
{
System.out.print("I like to ");
consume();
consume();
consume();
fruit();
}
}
- 9
- Look at the frame on the bottom of the stack diagram to determine the current method.
- 11
- Correct. The bottom stack frame shows the current method is greet() and line 11 is next to execute.
- 19
- Look at the frame on the bottom of the stack diagram to determine the current method.
- 20
- Look at the frame on the bottom of the stack diagram to determine the current method.
5-1-9: Given the stack diagram shown in the figure, which line is next to execute?
- 16
- Look at the main method frame in the stack diagram.
- 17
- Look at the main method frame in the stack diagram.
- 18
- Look at the main method frame in the stack diagram.
- 19
- Correct. The main method frame shows the greet method was called at line 19.
5-1-10: After line 12 executes and the greet() method completes, control will return to which line in the main method?
- line 21 in method main.
- Incorrect. The stack diagram shows method n was called by method m.
- line 6 in method o.
- Incorrect. The stack diagram shows method n was called by method m.
- line 16 in method m.
- Correct. The stack diagram shows method n was called by method m.
5-1-11: Notice the n() method is called both in method o() and method m(). The stack diagram shows the current execution trace. After line 12 executes and the n() method completes, control will return to which line in which method?
- Called n
- Incorrect. The last method call in the main is to method o(). Look at the last line in method o().
- Called o
- Incorrect. The last method call in the main is to method o(). Look at the last line in method o().
- Called m
- Incorrect. The last method call in the main is to method o(). Look at the last line in method o().
- After n
- Correct.
5-1-12: What is the last thing printed when the program runs?
A refrain is similar to a chorus, although usually shorter in length such as a single line that gets repeated. In the song below, the refrain is “The farmer in the dell”. Add a method named “refrain” and update the main method to call the new method 3 times in place of the duplicate print statements. Run your program to ensure the output is correct.
5.1.3. Summary¶
Procedural Abstraction (creating methods) reduces the complexity and repetition of code. We can name a block of code as a method and call it whenever we need it, abstracting away the details of how it works.
A programmer breaks down a large problem into smaller subproblems by creating methods to solve each individual subproblem.
Write a method definition with a method signature like
public static void chorus()
and a method body that consists of statements nested within {}.Call the method using its name followed by parentheses
chorus()
. The method call executes the statements in the method body.