Methods 2

Things To Do First

Things To Do Later

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 or parameters. Even though we sometimes use these two terms interchangeably, you'll see later that we also refer to parameters as something else inside a method definition. For this reason, we will try to refer as a method's input values 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 later in Chapter 5 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:

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:

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:

parameter variables in memory

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

Exercises

[solutions]

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?

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.

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.");
    }
}
Note
To get the current year, try this code:
int currYear = Calendar.getInstance().get(Calendar.YEAR);

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:

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 the second course 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

[solutions]

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.

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.

Return Values

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 num to the power of exp as a double value. This method returns a value, which is the result of the calculation numexp.

Another example 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.

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 may not 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.

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

[solutions]

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:

  • getDoubleInput()
    Inputs: a prompt to display to the user, asking for a numeric value
    Returns: a double value that was entered by the user
    This method displays prompt to the user on the console, then uses a Scanner object to retrieve a double value from the user. The method then returns the value entered. You can add some validation to this method if you wish.
  • calcTip()
    Inputs: a bill amount, a tip percentage
    Returns: a tip amount in dollars
    This method calculates a dollar amount to tip a wait person by multiplying the bill amount by the tip percentage (as a decimal).
  • displayAmt()
    Inputs: a dollar amount to display
    Returns: nothing
    This method receives a dollar amount and displays it formatted with a dollar sign and exactly two decimal places on the console