CS 302 Lab 4

Lab 4: Static Methods

CS302, UW-Madison

Today we'll cover:

Overview

Writing an entire program in the main method gets very messy even for moderate-sized programs of a few hundred lines. A better approach is to divide that code into modules that are designed to solve particular tasks. In Java, we use methods to organize our code into modules, which will improve our program's readability, make it easier to maintain and update, and reduce redundancy in our code. Structuring a program to use methods also frees the main method of all of the details for each task allowing it to have just the high-level "main" aspects of a program.

You've been using a particular kind of method, called an instance method, when you coded statements in lab 1 such as puss.forward() and puss.right(), and in lab 2 ranGen.nextInt(6). To use a instance method we must say which software object we want to do the method: the cat puss and the random number generator ranGen in the examples above.

This lab introduces you to a different kind of method called a static method, so named because the reserved word static is in the method's header. The main method is a static method as are the methods in the Math class. Static methods aren't associated with software objects, and do not require that we know object-oriented programming. Because of this, we'll learn about static methods first. Later, we'll learn how to program our own software objects and non-static methods.

Getting started

Start by making a new project in Eclipse named MethodsLab. When creating the new project, remember to select "Use project folder as root for sources and class files" in the "Project layout" section. Download PrimeMethods.java and save it in your project folder (right click and choose "Save Link As...", navigate to your project folder, save the file, select your project in Eclipse and hit "F5" to refresh your project).

Task 1: Explore the parts of a Method

Begin by taking a look at the code that you've downloaded. Observe the difference in the structure of this program from the programs you've written so far. Run this program a few times. Does it do what you expect it to? Recall that a prime number is an integer that is evenly divisible only by 1 and itself. The first few primes are 2, 3, 5, 7, and 11.

Now look at the method isPrime. How would you know that it is a static method? Methods are designed to work like mathematical functions such as "square root". For square root to work we need to provide information, a number, and we expect to get an answer back, the square root of the number we provided. Note that the isPrime method is given a number and returns an answer that says whether or not the given number is prime.

The isPrime method is used by the main method in the line of code copied below:

if (PrimeMethods.isPrime(userNumber))

What's underlined above is a method call. Static methods are called using the following form:

<ClassName>.<methodName>(<arguments>)

The information we provide when we call a method is referred to as the parameter values (also known as arguments). For our program, we provide the isPrime method the value in variable userNumber, which is underlined in the code below:

if (PrimeMethods.isPrime(userNumber))

Where does the isPrime method store this value? In its parameter variable (also known simply as a parameter). Methods store their parameter values in their parameter variables, which are listed in the method's header in the parentheses after the method name. Like variable declarations, parameter variables must first specify their type and then their name. In our code, the isPrime method has one parameter variable, named number, of type int, as underlined in the code:

public static boolean isPrime(int number)

A method can have more than one parameter if needed, or zero parameters if no information needs to be provided to the method.

We also need to specify what type of answer is returned by a method. We call this the return type, and it is listed in the method header right before the method's name. In our code, the isPrime method specifies it will return a boolean answer, as underlined below:

public static boolean isPrime(int number)

If a method doesn't return anything, we use the type void. Notice the return type of the main method.

The method's body, enclosed in braces, follows after the method's header. Here's where we put the statements that implement the method's algorithm so that it does the task indicated by the method's name. Take a look at the code that determines if a number is prime. Our implementation is very simple. (One of the challenges below is to improve efficiency of this method.) Together, a method header and its body are called a method definition.

Task 2: Use a Method

Let's give this a try! Beneath isPrime is another completed method called findMinPrimeFactor. This method has one parameter, just like isPrime, but it returns an int instead of a boolean.

Some Math: Every positive integer can be written as a product of prime numbers. This is a number's prime factorization. Each integer has a unique set of primes that produce it when multiplied together. Here are some examples of prime factorizations:
IntegerFactorization
42 * 2 (or 22)
1111
153 * 5
242 * 2 * 2 * 3 (or 23 * 3)
393 * 13

Because a factorization is a product of primes, multiplying two numbers just combines their factors. So 60 = 4 * 15 = (2 * 2) * (3 * 5), and the prime factorization of 60 is 2 * 2 * 3 * 5.

First, add code to main that calls the findMinPrimeFactor method, using userNumber. Display the user's number, the number that the method returns and the value of the user's number divided by the return value. Next, modify your code to print the prime factorization of userNumber. To do this, you'll need to repeatedly find and display the minimum prime factor and divide the number by that factor until the number has been reduced to 1. Don't worry about formatting; just print all the factors the correct number of times.

Task 3: Finish a Method

Now you'll implement a method's body on your own. At the bottom of the PrimeMethods class is an incomplete method, named findGreatestCommonDivisor. This method is given two numbers as parameter values and returns the largest integer that divides both of them. Start this task by commenting out your code in the main method for tasks 1 and 2, and uncommenting the task 3 code below it.

There are several ways to do this, one way is to determine the factors of one of the numbers working from largest to smallest. Start with the factor being the number divide by 2 (using integer division) and work your way down to 2 decrementing the factor by 1 each time. When you find a factor, see if it divides evenly into the other number. If so, return the first one you find as the answer.

Another more challenging way is to use your algorithm in task 2 to find the prime factors of both numbers. Rather than displaying them, use two arrays, one for each number, to store all of the prime factors of each number. Then, multiply the prime factors they share in common to determine the answer.

Task 4: Write Your Own Method

Now, create a new class containing a main method and another static method that does one of the tasks below. Your main method gets input from the user and prints the answer that it gets from the other static method you'll write to do some task. Most of these problems have multiple possible solutions. Be creative!

Challenge Tasks (Optional)

Challenge 1

Write a method nthPrime that calculates the nth smallest prime number.

Challenge 2

Choose a second problem from task 4 and solve it.

Challenge 3

Improve the efficiency of the isPrime code in task 1 so that it reduces the number of unnecessary divisions.