Overview of This Lesson

Methods (called "functions" in some other languages) are an important part of programming. You've already used several methods such as System.out.println(), Math.pow(), and input.nextInt(). You can also create your own methods so that your code is more modular and re-usable, and so you can encapsulate complex or detailed tasks.

In this lesson you'll learn how to create your own static methods, and learn more about modularization, re-usability, and encapsulation.

Pre-Requisties

Before doing this lesson, make sure you've learned about selections and loops, and that you're comfortable getting input using the Scanner class.

Why Use Methods?

What is a method? A method is basically a collection of statements that are placed together to perform some kind of task or operation.

Programmers write methods to modularize their programs. Program modules are smaller segments of program logic or code dedicated to a specific task. Modular programs are much easier to debug and maintain.

Another reason programmers write methods is to make program code reusable. If you have a common programming task, you can put it in a method and then reuse it whenever you want without re-writing it every single time.

Lastly, we write methods as a way of providing abstraction: hiding details that aren't important. When you use Math.pow(), you know how to use it, you don't care how it actually works on the inside.

Modularization

Most programs you will write are going to be large and complex. Programmers develop these kinds of programs by breaking them up into smaller, more manageable tasks. Each task or module is coded into its own method. As a simple example, say a program calculates an employee's paycheck. You might have a sequence of methods such as:

  1. Get inputs (hours worked, rate of pay)
  2. Calculate gross pay
  3. Calculate tax deductions
  4. Calculate insurance deductions
  5. Calculate other deductions
  6. Calculate net pay
  7. Print paycheck
  8. Update payroll files

Re-usability

We also mentioned that we use methods to make code re-usable. Methods can help eliminate redundant code. Code that appears repeatedly are harder to maintain and debug, so programmers try to avoid repeating code. Methods are one way to do this. For example, imagine you are asking the user for the dimensions to calculate the volume of a three-dimensional rectangle:

import java.util.Scanner;

public class RectangleVolume {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        // get length
        System.out.println("Please enter the length.");
        double length = in.nextDouble();

        // get width
        System.out.println("Please enter the width.");
        double width = in.nextDouble();

        // get height
        System.out.println("Please enter the height.");
        double height = in.nextDouble();

        // calculate and display volume
        double volume = length * width * height;
        System.out.printf("The volume is %.2f.%n", volume);
    }
}

Here we are asking for three different values. We can make this code smaller and eliminate redundancy by using a method to get the user inputs.

Abstraction

The goal of abstraction is to hide the unnecessary details or internal workings of your code from the person using it (generally, another programmer). For example, if you create a method that calculates the average value in an array of integers, the person using your method doesn't need to know all the details of what's going on inside the method. They only need to know:

  1. What the method does (calculates the average of an integer array)
  2. What the method needs in order to do #1 (an array of integers)
  3. What the method returns, if anything, and what data type (a double value containing the average of all the array elements)

If you wrote this method and added a note such as "you must make sure your integer array is defined globally and called 'numbers'.." then you're not practicing abstraction: you're not hiding all the details inside the method. You're creating a method that is going to be difficult, if not impossible, to use.

Defining A Method

A method definition starts with a method header. The method's code goes inside a method block (between opening and closing braces). For example, you're already familiar with the main() method:

public static void main(String[] args) {
    // code goes here
}

Not all method headings will be the same. For example, this method is called getUserInput(), and likely retrieves a value from the user:

public static String getUserInput(String msg) {
    // method's code goes here
}

In general, a method's heading includes:

Introductory Examples

Let's start with a simple demonstration of how methods work. Enter the following program into your editor:

public class TestMethods {

    public static void main(String[] args)  {

        System.out.println("This is my main() method.");
        displayName();
        System.out.println("My main() method is finished.");
    }

    public static void displayName() {
        System.out.println("This is my displayName() method.");
        System.out.println("My name is [type your name here].");
        System.out.println("My displayName() method is finished.");
    }
}

The code that makes up a method goes in between the braces. In our program there are two methods: the main() method is defined from lines 03 to 08, and the displayName() is defined from lines 10 to 14.

On line 06 of the main() method you'll notice the method displayName() followed by a semi-colon. This is the method invocation or method call for the displayName() method. This is the statement that tells the computer to go and find the displayName() method and execute the statements inside it. When the computer gets to line 06, program execution will move to the displayName() method. All the statements inside the method will be executed, and then program control moves back to line 06 in the main() method. At this point, the program will continue with line 07, and then the program will terminate.

If you run this program, you'll get the following output:

This is my main() method.
This is my displayName() method.
My name is [type your name here].
My displayName() method is finished.
My main() method is finished.

Notice that the first and last line of output are the print statements in the main() method. The middle three lines are from the displayName() method.

Exercises

1. Write a program with a method called displayGreeting(). This method should display a greeting to the user (you decide what kind of greeting you'd like.. maybe something like "Hello, Welcome to my program that uses methods!") Your main method should invoke the greeting method, and then display a closing message (such as "Goodbye, and thanks for all the fish!").

2. Modify the program in the previous exercise: put your closing message in a method called displayClosing(). Modify your main() method to invoke the greeting method, display some other text, and then invoke the closing method.

3. Manually trace the following program and determine the output, then run the program to see if you were correct.

public class TestMethods2 {
    public static void main(String[] args) 	{
    
        System.out.println("I have some methods:");
        displayOne();
        System.out.println("That's all!");
    }
    
    public static void displayOne() {
        System.out.println("This is method one.");
        displayTwo();
        System.out.println("Going back to main...");
    }
    
    public static void displayTwo() {

    }
}

4. Write a program that has a method called displayName(). This method should use a Scanner to ask the user for their name, then display that name on the screen in the form "Hello, [user name]!" (where [user name] is the name input by the user. The program's main() method should invoke the displayName() method, then display the message "Good bye!".

5. Write a program that displays "I love Java!" on the screen 10 times. Use a method called displayJava() to display the text 10 times.

Question 1:

question 1 solution
Question 1. display greeting

Question 2:

question 2 solution
Question 2. display closing

3.

I have some  methods:
This is method one.
This is method two.
Going back to main...
That's all!

Question 4:

question 4 solution
Question 4. display personal greeting

Question 5:

question 5 solution
Question 5. display java 10 times

Arguments and Parameters

Some methods require information in order to work. For example, the println() and print() methods need to know what value(s) you want to print. To give print() and println() this information, you type the values inside the brackets. The inputs you give to a method in this manner are refered to as arguments.

Arguments

An argument can be a literal value or an expression. For example, all of these println() methods contain valid arguments:

// one string literal argument:
System.out.println("Hello, World!");

// one argument - an expression with 2 string 
// literals and a variable
System.out.println("Hello, " + userName + "!");

// one argument - an expression with a string literal
// and a mathematical expression
System.out.println("Sum of my numbers: " + (num1 + num2 + num3));

All of these println() methods have only one argument each. In the last two examples, those arguments consist of an expression where different literals and values are concatenated together. Be sure you understand that when an expression is "built" as in these examples, the result is still only one argument! The expression is evaluated first, and the final result is the argument.

A second and more interesting example is the printf() method. With this method, we specify multiple arguments: A format string, and then a series of values that are to replace the format specifiers in the format string.

When a method requires more than one argument, we separate them with a comma:

System.out.printf("%d / %d = %.2f%n", var1, var2,
(double)var1 / var2);

When we give arguments to a method, we say that we are passing arguments into the method or passing values into the method. This means that a method is receiving one or more inputs in the form of these arguments.

When you are invoking a method, you must always know what arguments the method requires, if any, and the data types of these methods. For example, the printf() method requires that the format string be first, and that it be a valid string. It also requires that this argument must then be followed by a series of arguments that match each individual format specifier in the string by data type. We would not be allowed to change the order or type of the arguments, or else our method won't work properly.

Some methods have optional arguments, so you must make sure you are careful when you are passing arguments that you don't forget to include the arguments that are required. Some methods will also allow you to pass in different kinds of data for a single argument. For example, these two print methods are both valid:

System.out.print("hello");
int num = 4;
System.out.print(num);

In this case, the print() (and println()) method will take a string value, or even a numeric value. We'll learn in a later lesson why both of these will work, but know that not all methods work this way.

Parameters

A method that requires arguments in order to work must have parameter variables defined in the method header. Parameter variables are special variables that hold or store the values passed into the method.

For example, enter the following program into your editor:

import java.util.Scanner;

public class TestParams {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);
        System.out.print("Enter your name: ");
        String userName = in.nextLine();
        displayGreeting();
    }

    public static void displayGreeting() {
        System.out.println("Hello, " + userName + "!");
    }
}

What happens when you compile this program? You will get the following error (or something similar):

TestParams.java:14: cannot find symbol
symbol  : variable userName
location: class TestParams
System.out.println("Hello, " + userName + "!");
                                ^
1 error

Why does the computer think that the variable userName is undefined? Recall what we discussed earlier with variables in methods: a variable is only available in the method in which is is defined. In this case, the userName variable is local to the main() method; it is declared in the main() method, so that's the only place we can access it. You can't access the userName variable in the displayGreeting() method because this method has no idea that userName exists.

This is definitely a problem -- how can we make the userName variable available to the displayGreeting() method? This is a perfect reason for using arguments and parameters!

What we need to do is give the userName we've captured to the displayGreeting() method so that displayGreeting() can use it. In other words, we need to pass the userName value into the displayGreeting() method. The calling statement should include an argument for userName, since we want to send userName as an input to the displayGreeting() method:

import java.util.Scanner;

public class TestParams {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);
        System.out.print("Enter your name: ");
        String userName = in.nextLine();
        displayGreeting(userName);
    }

    public static void displayGreeting() {
      System.out.println("Hello, " + userName + "!");
    }
}

Now that you've modified the code to pass the userName argument into the displayGreeting() method, you have to alter the method so that it's ready to receive the argument's value. To do this we add a parameter statement to the displayGreeting() method's heading:

import java.util.Scanner;

public class TestParams {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);
        System.out.print("Enter your name: ");
        String userName = in.nextLine();
        displayGreeting(userName);
    }

    public static void displayGreeting(String name) {
        System.out.println("Hello, " + name + "!");
    }
}

A parameter statement looks like a variable declaration, and it really is declaring a special kind of variable (a parameter variable). The parameter statement sets aside a spot in memory (in this case, a location that will be referred to as name and that will hold String values). This memory location will contain the value that was passed into the method. In this case, the value of the userName argument will go into the name paramter.

Let's say we run this program now and the user types "Kaluha" into the input dialog. This string value will be stored in the variable userName, which is local to the main() method. Then we invoke or call the displayGreeting() method and pass it the userName variable. In reality, we are only taking a copy of the value in userName and storing it in the parameter variable name. If you were to imagine the computer's memory when the displayGreeting() method began, it might look something like this:

variable user name in memory, it's value is passed to user name parameter variable
parameter variables in memory

Now try compiling and running the program. It should work fine.

Exercises

1. Add a method to your example called guessAge(). This method should accept an integer for a year. The program should then display a "guess" of the user's age by subtracting the year parameter value from the current year. Your main() method will need to get the year of birth from the user and pass that into the guessAge() method!

2. What happens if you try to pass a string into the guessAge() method? What if you try to pass an integer or double into the displayName() method?

Question 1:

question 1 solution
Question 1. estimate age

2. If you try to pass a String into the guessAge() method, you get an error because the method is expecting an integer, but instead you passed it a String.

Multiple Arguments

When a method requires more than one argument, we must include a parameter variable for each argument. Each parameter variable is separated by commas. For example, write a program that has a method called displaySeconds() that takes integer values for a number of hours, minutes, and seconds, and calculates and displays the total number of seconds (hours * 3600 + minutes * 60 + seconds). The program's main() method should prompt the user for the number of hours, minutes and seconds.

The main method needs to use the input dialog to get the three time values, and then pass those three values into the displaySeconds() method. You will need to separate each argument with a comma:

import java.util.Scanner;

public class TimeStuff {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);

        // get the hours, minutes, and seconds from the user
        System.out.print("Enter the number of hours.");
        int hours = in.nextInt();
        System.out.print("Enter the number of minutes.");
        int mins = in.nextInt();
        System.out.print("Enter the number of seconds.");
        int seconds = in.nextInt();
	
        // display the total seconds
        displaySeconds(hours, mins, seconds);
    }

}

Notice that we have placed the three arguments or inputs in the brackets and separated them with commas.

The displaySeconds() method now needs to include three parameter variables for each of the arguments:

import java.util.Scanner;

public class TimeStuff {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);

        // get the hours, minutes, and seconds from the user
        System.out.print("Enter the number of hours.");
        int hours = in.nextInt();
        System.out.print("Enter the number of minutes.");
        int mins = in.nextInt();
        System.out.print("Enter the number of seconds.");
        int seconds = in.nextInt();
	
        // display the total seconds
        displaySeconds(hours, mins, seconds);
    }

    public static void displaySeconds(int hours, int mins, int seconds) {

        int totalSeconds = hours * 3600 + mins * 60 + seconds;
		    System.out.println("Total Seconds: " + totalSeconds);
    }
}

Notice that this time the parameter names are the same as the argument variable names from the main() method. This is okay, in that it won't cause our program to crash and won't generate any kind of compile errors. Remember that these two sets of variables are separate locations in memory, and the computer is able to keep track of the scope (i.e. that one set is from the main() method and one set is for the displaySeconds() method's parameters).

The order in which you pass the arguments to a method depends on the order in which the parameter variables are defined. For example, what would happen to our program if my call to displaySeconds() was written as:

displaySeconds(seconds, hours, mins);

This will change cause our program to display incorrect output because the value of the seconds argument is going into the hours parameter variable in the displaySeconds() method.

mapping each argument value into its correct parameter variable
multiple parameters

You should always make sure you pass your arguments in the right order. In some cases, this can cause a compile error. To see how, copy the following code and compile it:

import java.util.Scanner;

public class TestParams2 {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        System.out.print("Please enter your name.");
        int yearBorn = in.nextInt();

        displayThings(name, yearBorn);
    }

    public static void displayThings(String name, int year) {		
        int age = 2006 - year;
        System.out.println("Hi, " + name + ". You are about "
            + age + " years old.");
    }
}

Once you see how the program works, change the order of the arguments around in the calling statement for displayThings():

displayThings(yearBorn, name);

You'll receive the following message (or something similar):

TestParams2.java:22: displayThings(java.lang.String,int) in TestParams2 cannot 
  be applied to (int,java.lang.String)
          displayThings(yearBorn, name);
          ^
  1 error

Here the error is telling you that the method displayThings() takes a string and an int, but you are attempting to pass it an int and a string, instead.

Always make sure you are passing your arguments in the right order! They must always match in type and number.

A common question at this point is, "..so how do I know what order and types of arguments a method requires?" This is what documentation is for! In an upcoming course or lesson you'll learn how to properly document your methods and classes using the javadoc tool. When you're learning a new method that is already part of the Java language, or written by another programmer, you can view the javadocs for the class the method belongs to. For example, we have used the javadocs to learn about methods in the Math class. If you go and look up the methods max(), pow(), and sqrt() methods, you can see what numbers and types of arguments these methods require.

Exercises

1. For each of the following method headers, determine the number, type and sequence of the values that must bepassed to the method.

  1. public void factorial(int n)
  2. public void getPrice(int type, double yield, double maturity)
  3. public void getInterest(char flag, double price, double time)
  4. public void backwards(String sentence)

2.Manually trace the following program and determine the output, then run the program to see if you were correct.

public class TestScope {

    public static void main(String[] args) 	{

        int number = 1;
        System.out.println("in main: ");
        System.out.println("1. " + number);
        oneMethod(number);
        System.out.println("2. " + number);
        twoMethod();
        System.out.println("3. " + number);
    }

    public static void oneMethod(int number) {
        System.out.print("  m1: ");
        System.out.print(number);
        number++;
        System.out.println(" " + number);
    }

    public static void twoMethod() {
        int number = 10;
        System.out.print("  m2:");
        System.out.println(" " + number);
    }
}

3. Write a program that retrieves a final grade from the user and displays the corresponding letter grade on the screen. Your program should invoke a method called getAlpha() that accepts the final grade as an argument and displays the letter grade on the screen. Use the following table to assign letter grades:

Grading System
Grade Range Alpha Grade
90 and higher A+
80 and higher, up to 90 A
75 and higher, up to 80 B+
70 and higher, up to 75 B
65 and higher, up to 70 C+
60 and higher, up to 65 C
50 and higher, up to 60 D
under 50 F

4. Write a program that calculates and displays the area and circumference of a circle. Your program should prompt the user to enter the radius. Your program should also include two methods: getCircumference() calculates and displays the circumference (2 * PI * radius) of the circle and getArea() calculates and displays the area (PI*radius2) of the circle. Both of these methods will require the radius, so radius should be passed into each method.

1.

  1. public void factorial(int n): a single int value
  2. public void getPrice(int type, double yield, double maturity): an int value, and then 2 double values
  3. public void getInterest(char flag, double price, double time): a char value, and then 2 double values
  4. public void backwards(String sentence): a single string value

2.

in main: 
1. 1
  m1: 1 2
2. 1
  m2: 10
3. 1

Question 3:

question 3 solution
Question 3. get alpha grade

Question 4:

question 4 solution
Question 4. area and circumference of circle

Returning A Value

Many methods perform a task and then produce a result that is given back to the programmer. For example, Math.pow(num, exp) accepts a value num and an exponent exp, and gives the programmer the result of numexp as a double value. This method returns a value, which is the result of the calculation num to the power of exp.

Another set of examples are the next---() methods in Scanner: nextInt() returns the int value typed by the user; the nextDouble() method returns the double value typed by the user; the nextLine() method returns an entire line of text typed by the user as a String.

nextInt sending a value into a variable called num
Scanner's nextInt() method returns an int entered by the user and stores it in the variable num.

Methods like print(), printf(), and println() don't return values. They simply display their information on the screen. They don't send any values back to the programmer. These are called void methods because when you define methods that return nothing, they include the word void in the method header. You wrote void methods in the previous section, such as displayGreeting() and and displaySeconds().

Methods Return a Single Value

When methods return a value, it is always a single value. In other words, a method is not permitted to return multiple values (although you can get around this by having your method return an array, but still an array is a single value ;) ). When you call or invoke a method that returns a value, you must store that value somewhere. For example:

int number = in.nextInt();

In the code above, the nextInt() method of the Scanner object grabs an int value from the keyboard and returns it. We then take that int value and store it in the variable "number".

If we like, we can then use that return value, such as in a print statement, or in an expression:

import java.util.Scanner;

public class ReturnValues {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);
        System.out.print("Enter a number: ");
        int number = in.nextInt();
        System.out.println("Your number is " + number + ".");
    }
}

A Common Error!

It is a common error for new programmers to attempt the following:

import java.util.Scanner;

public class ReturnValues {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);
        System.out.print("Enter a number: ");
        in.nextInt();
    }
}

When a method returns a value, you must make sure you store that value somewhere! In this code, the nextInt() method is returning an int, but it's not being saved anywhere! If you don't save the return value, it's gone forever and you have no way of getting it back again (unless you call the method a second time, which would be inefficient and unnecessary).

Why Return Values?

When designing your own methods, why would you want a method to return a value? Think back to the program that asked the user for hours, minutes, and seconds. Did you write the statement that captured the hours using an Scanner, and then copy-pasted twice to add the statements for minutes and seconds? This is a common issue in programming: if you copy-paste sections of code, it's likely that you're using redundant statements. In this example, we're asking for three input values, and the only things that are different for each statement is the thing we're asking for. We can "streamline" this code by using a method to prompt the user for a time value and returning the value we retrieve. It means that we don't have to type the statement that grabs inputs three times!

Before we tackle this solution, let's do a simpler one in the same program so we can see how returning values works:

Write a program that contains a method called calcPerimSquare(). The method accepts a double value representing the size of a square's side, and then returns an the perimeter of a square of that size by multiplying the size by 4.

It is important to figure out what a method needs for inputs (its arguments) and what a method outputs (its return value). Note that a method can have more than one input (or none!) but it can have only one return value!

This method requires an argument for the square's size, and it will return a double for square's perimeter. Some programmers like to write an IPO chart for methods like this one:

Inputs: size of a square's side
Processing: perimeter = size * 4
Outputs: the perimeter of a square with a specific size

When a method returns a value, you have to indicate this in the method header. So far all our methods have been void methods. "Void" means "nothing", or no return value. Therefore, a void method is a method that returns no value, or returns nothing. When a method returns something, you have to replace the "void" with a proper data type. In our case, the method will return an double, so our method header will appear as:

public static double calcPerimSquare(double size) {
...
}

Notice that we also remembered to include the size parameter variable!

The body of our method will perform the processing:

public static double calcPerimSquare(double size) {
    double perimeter = size * 4;
}

The last step is to ensure that the value in age gets returned by the method. This is what causes the value to come out of the method and into a variable our output statement. For this, we use a "return" statement:

public static double calcPerimSquare(double size) {
    double perimeter = size * 4;
    return perimeter;
}

Some programmers like to take a short cut and type:

public static double calcPerimSquare(double size) {
    return size * 4;
}

In a small program like this one, either is acceptable.

To use this method, we have to make sure that the value being returned ends up being stored somewhere or being output somewhere. Recall the example previously where the input dialog was not in a proper assignment statement -- we want to avoid this!

import java.util.Scanner;

public class CalcPerimeter {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);
        System.out.print("Enter the size of the square: ");
        double squareSize = in.nextDouble();
        double perim = calcPerimSquare(squareSize);
        System.out.printf("Perimeter: %.2f%n", perim);
    }

    public static double calcPerimSquare(double size) {
        return size * 4;
    }
}

In this case, we're telling the program to place the value returned by calcPerimSquare() into the variable perim. When placing the output of a method into a variable, you must make sure that the variable's data type is the same data type as the method's return value (or you'll have to parse the method's output).

You could also print the method's result right on the console:

import java.util.Scanner;

public class CalcPerimeter {

    public static void main(String[] args) 	{

        Scanner in = new Scanner(System.in);
        System.out.print("Enter the size of the square: ");
        double squareSize = in.nextDouble();
        System.out.printf("Perimeter: %.2f%n", calcPerimSquare(size));
    }

    public static double calcPerimSquare(double size) {
        return size * 4;
    }
}

The only difference between these two approaches is that in the first one, you're saving the result to the variable perim, so you can use it later on in the program if you wish. In the second example, the result is being sent directly to the console, so you have no way of retrieving that value again. You could, of course, just invoke calcPerimSquare(size) again, however calling a method over and over when you don't have to is very inefficient! If you need to call a method over and over to obtain the exact same value, call it once and store the return value in a variable.

Exercises

1. What happens if you change the data type of perim to an int? What if you change it to a String?

2. How are these two statements different?

calcPerimSquare(size);
double perim = calcPerimSquare(size);

Which one is incorrect and why?

3. a) Modify question 3 in the previous set of exercises to make the getAlpha() method return the alpha grade, and have the main() method display the alpha grade.

3. b) Modify question 4 in the previous set of exercises to have the getArea() and getCircumference() methods return their values instead of displaying them. Modify the main() method so that the values are displayed there.

4. Write a tip calculator that allows a restaurant or bar customer to calculate the amount of a tip to give their wait person. The program should allow the customer to specify the bill amount and the percentage of tip they would like to give.

The program should include the following methods:

1. If you change the perim variable's data type to an int or to String, your program won't compile because calcPerimSquare() returns a double, and you can't put a double into an int or a String.

2. The two statements are different in that the first one doesn't store the return value anywhere - the perimeter returned by the method is not stored or output. The second statement does store the method's return value in a variable, so it can be used later.

Question 3a:

question 3a solution
Question 3a. get alpha grade

Question 3b:

question 3b solution
Question 3b. area and circumference of circle

Question 4:

question 4 solution
Question 4. tip calculator