Chapter 19

Creating New Java Methods

In This Chapter

arrow Writing methods that work with existing values

arrow Building methods that modify existing values

arrow Making methods that return new values

In Chapters 3 and 4, I introduce Java methods. I show you how to create a main method and how to call the System.out.println method. Between that chapter and this one, I make very little noise about methods. In Chapter 18, I introduce a bunch of new methods for you to call, but that’s only half of the story.

This chapter completes the circle. In this chapter, you create your own Java methods — not the tired old main method that you’ve been using all along, but some new, powerful Java methods.

Defining a Method within a Class

In Chapter 18, Figure 18-6 introduces an interesting notion — a notion that’s at the core of object-oriented programming. Each Java string has its own equals method. That is, each string has, built within it, the functionality to compare itself with other strings. That’s an important point. When you do object-oriented programming, you bundle data and functionality into a lump called a class. Just remember Barry’s immortal words from Chapter 17:

A class describes the way in which you intend to combine and use pieces of data.

And why are these words so important? They’re important because in object-oriented programming, chunks of data take responsibility for themselves. With object-oriented programming, everything you have to know about a string is located in the file String.java. So if anybody has problems with the strings, they know just where to look for all the code. That’s great!

So this is the deal — objects contain methods. Chapter 18 shows you how to use an object’s methods, and this chapter shows you how to create an object’s methods.

Making a method

Imagine a table containing the information about three accounts. (If you have trouble imagining such a thing, just look at Figure 19-1.) In the figure, each account has a last name, an identification number, and a balance. In addition (and here’s the important part), each account knows how to display itself on the screen. Each row of the table has its own copy of a display method.

Figure 19-1: A table of accounts.

9780470371749-fg1901.tif

The last names in Figure 19-1 may seem strange to you. That’s because I generated the table’s data randomly. Each last name is a haphazard combination of three letters — one uppercase letter followed by two lowercase letters.

technicalstuff.eps Though it may seem strange, generating account values at random is common practice. When you write new code, you want to test the code to find out if it runs correctly. You can make up your own data (with values like “Smith”, 0000, and 1000.00). But to give your code a challenging workout, you should use some unexpected values. If you have values from some real-life case studies, you should use them. But if you have don’t have real data, randomly generated values are easy to create.

To find out how I randomly generate three-letter names, see this chapter’s “Generating words randomly” sidebar.

I need some code to implement the ideas in Figure 19-1. Fortunately, I have some code in Listing 19-1.

Listing 19-1: An Account Class

import java.text.NumberFormat;

import static java.lang.System.out;

class Account {

    String lastName;

    int id;

    double balance;

    void display() {

        NumberFormat currency =

            NumberFormat.getCurrencyInstance();

            

        out.print(“The account with last name “);

        out.print(lastName);

        out.print(“ and ID number “);

        out.print(id);

        out.print(“ has balance “);

        out.println(currency.format(balance));

    }

}

The Account class in Listing 19-1 defines four things — a lastName, an id, a balance, and a display. So each instance of Account class has its own lastName variable, its own id variable, its own balance variable, and its own display method. These things match up with the four columns in Figure 19-1.

Examining the method’s header

Listing 19-1 contains the display method’s declaration. Like a main method’s declaration, the display declaration has a header and a body (see Chapter 4). The header has two words and some parentheses:

check.png The word void tells the computer that, when the display method is called, the display method doesn’t return anything to the place that called it.

Later in this chapter, a method does return something. For now, the display method returns nothing.

check.png The word display is the method’s name.

Every method must have a name. Otherwise, you don’t have a way to call the method.

check.png The parentheses contain all the things you’re going to pass to the method when you call it.

When you call a method, you can pass information to that method on the fly. This display example, with its empty parentheses, looks strange. That’s because no information is passed to the display method when you call it. That’s okay. I give a meatier example later in this chapter.

Examining the method’s body

The display method’s body contains some print and println calls. The interesting thing here is that the body makes reference to the variables lastName, id, and balance. A method’s body can do that. But with each object having its own lastName, id, and balance variables, what does a variable in the display method’s body mean?

Well, when I use the Account class, I create little account objects. Maybe I create an object for each row of the table in Figure 19-1. Each object has its own values for the lastName, id, and balance variables, and each object has its own copy of the display method.

So take the first display method in Figure 19-1 — the method for Aju’s account. The display method for that object behaves as if it had the code in Listing 19-2.

Listing 19-2: How the display Method Behaves When No One’s Looking

/*

* This is not real code:

*/

void display() {

    NumberFormat currency =

        NumberFormat.getCurrencyInstance();

        

    out.print(“The account with last name “);

    out.print(“Aju”);

    out.print(“ and ID number “);

    out.print(9936);

    out.print(“ has balance “);

    out.println(currency.format(8734.00));

}

In fact, each of the three display methods behaves as if its body has a slightly different code. Figure 19-2 illustrates this idea for two instances of the Account class.

Calling the method

To put the previous section’s ideas into action, you need more code. So the next listing (see Listing 19-3) creates instances of the Account class.

Figure 19-2: Two objects, each with its own display method.

9780470371749-fg1902.tif

Listing 19-3: Making Use of the Code in Listing 19-1

import java.util.Random;

class ProcessAccounts {

    

    public static void main(String args[]) {

            

        Random myRandom = new Random();

        Account anAccount;

        for (int i = 0; i < 3; i++) {

            anAccount = new Account();

            anAccount.lastName = “” +

                (char) (myRandom.nextInt(26) + ‘A’) +

                (char) (myRandom.nextInt(26) + ‘a’) +

                (char) (myRandom.nextInt(26) + ‘a’);

                

            anAccount.id = myRandom.nextInt(10000);

            anAccount.balance = myRandom.nextInt(10000);

            anAccount.display();

        }

    }

}

Here’s a summary of the action in Listing 19-3:

Do the following three times:

    Create a new object (an instance of

        the Account class).

    Randomly generate values for the object’s lastName,

        id and balance.

    Call the object’s display method.

The first of the three display calls prints the first object’s lastName, id, and balance values. The second display call prints the second object’s lastName, id, and balance values. And so on.

A run of the code from Listing 19-3 is shown in Figure 19-3.

Figure 19-3: Running the code in Listing 19-3.

9780470371749-fg1903.tif

warning_bomb.eps Concerning the code in Listing 19-3, your mileage may vary. You don’t see the same values as the ones in Figure 19-3. In fact, if you run Listing 19-3 more than once, you (almost certainly) get different three-letter names, different ID numbers, and different account balances each time. That’s what happens when a program generates values randomly.

The flow of control

Suppose that you’re running the code in Listing 19-3. The computer reaches the display method call:

anAccount.display();

At that point, the computer starts running the code inside the display method. In other words, the computer jumps to the middle of the Account class’s code (the code in Listing 19-1).

After executing the display method’s code (that forest of print and println calls), the computer returns to the point where it departed from Listing 19-3. That is, the computer goes back to the display method call and continues on from there.

So when you run the code in Listing 19-3, the flow of action in each loop iteration isn’t exactly from the top to the bottom. Instead, the action goes from the for loop to the display method and then back to the for loop. The whole business is pictured in Figure 19-4.

Figure 19-4: The flow of control between Listings 19-1 and 19-3.

9780470371749-fg1904.eps

Using punctuation

In Listing 19-3, notice the use of dots. To refer to the lastName stored in the anAccount object, you write

anAccount.lastName

To get the anAccount object to display itself, you write

anAccount.display();

That’s great! When you refer to an object’s variable or call an object’s method, the only difference is parentheses:

check.png To refer to an object’s variable, you don’t use parentheses.

check.png To call an object’s method, you use parentheses.

remember.eps When you call a method, you put parentheses after the method’s name. You do this even if you have nothing to put inside the parentheses.

The versatile plus sign

The program in Listing 19-3 uses some cute tricks. In Java, you can do two different things with a plus sign:

check.png You can add numbers with a plus sign.

For example, you can write

numberOfSheep = 2 + 5;

check.png You can concatenate strings with a plus sign.

When you concatenate strings, you scrunch them together, one right after another. For example, the expression

“Barry” + “ “ + “Burd”

scrunches together Barry, a blank space, and Burd. The new scrunched-up string is (you guessed it) Barry Burd.

In Listing 19-3, the statement

anAccount.lastName = “” +

    (char) (myRandom.nextInt(26) + ‘A’) +

    (char) (myRandom.nextInt(26) + ‘a’) +

    (char) (myRandom.nextInt(26) + ‘a’);

has many plus signs, and some of the plus signs concatenate things together. The first thing is a mysterious empty string (“”). This empty string is invisible, so it never gets in the way of your seeing the second, third, and fourth things.

Onto the empty string, the program concatenates a second thing. This second thing is the value of the expression (char) (myRandom.next Int(26) + ‘A’). The expression may look complicated, but it’s really no big deal. This expression represents an uppercase letter (any uppercase letter, generated randomly).

Onto the empty string and the uppercase letter, the program concatenates a third thing. This third thing is the value of the expression (char) (my Random.nextInt(26) + ‘a’). This expression represents a lowercase letter (any lowercase letter, generated randomly).

Onto all this stuff, the program concatenates another lowercase letter. So altogether, you have a randomly generated three-letter name. For more details, see the sidebar.

technicalstuff.eps In Listing 19-3, the statement anAccount.balance = myRandom.next Int(10000) assigns an int value to balance. But balance is a double variable, not an int variable. That’s okay. In a rare case of permissiveness, Java allows you to assign an int value to a double variable. The result of the assignment is no big surprise. If you assign the int value 8734 to the double variable balance, then the value of balance becomes 8734.00. The result is shown on the first line of Figure 19-3.

remember.eps Using the double type to store an amount of money is generally a bad idea. In this book, I use double to keep the examples as simple as possible. But the int type is better for money values, and the BigDecimal type is even better. For more details, see Chapter 7.

Let the Objects Do the Work

When I was a young object, I wasn’t as smart as the objects you have nowadays. Consider, for example, the object in Listing 19-4. Not only does this object display itself, but the object can also fill itself with values.

Listing 19-4: A Class with Two Methods

import java.util.Random;

import java.text.NumberFormat;

import static java.lang.System.out;

class BetterAccount {

    String lastName;

    int id;

    double balance;

    void fillWithData() {

        Random myRandom = new Random();

        

        lastName = “” +

            (char) (myRandom.nextInt(26) + ‘A’) +

            (char) (myRandom.nextInt(26) + ‘a’) +

            (char) (myRandom.nextInt(26) + ‘a’);

              

        id = myRandom.nextInt(10000);

        balance = myRandom.nextInt(10000);

    }

    void display() {

        NumberFormat currency =

            NumberFormat.getCurrencyInstance();

            

        out.print(“The account with last name “);

        out.print(lastName);

        out.print(“ and ID number “);

        out.print(id);

        out.print(“ has balance “);

        out.println(currency.format(balance));

    }

}

I wrote some code to use the class in Listing 19-4. This new code is in Listing 19-5.

Listing 19-5: This Is So Cool!

class ProcessBetterAccounts {

    

    public static void main(String args[]) {

        

        BetterAccount anAccount;

        for (int i = 0; i < 3; i++) {

            anAccount = new BetterAccount();

            anAccount.fillWithData();

            anAccount.display();

        }

    }

}

Listing 19-5 is pretty slick. Because the code in Listing 19-4 is so darn smart, the new code in Listing 19-5 has very little work to do. This new code just creates a BetterAccount object and then calls the methods in Listing 19-4. When you run all this stuff, you get results like the ones in Figure 19-3.

Passing Values to Methods

Think about sending someone to the supermarket to buy bread. When you do this, you say, “Go to the supermarket and buy some bread.” (Try it at home. You’ll have a fresh loaf of bread in no time at all!) Of course, some other time, you send that same person to the supermarket to buy bananas. You say, “Go to the supermarket and buy some bananas.” And what’s the point of all this? Well, you have a method, and you have some on-the-fly information that you pass to the method when you call it. The method is named “Go to the supermarket and buy some. . . .” The on-the-fly information is either “bread” or “bananas,” depending on your culinary needs. In Java, the method calls would look like this:

goToTheSupermarketAndBuySome(bread);

goToTheSupermarketAndBuySome(bananas);

The things in parentheses are called parameters or parameter lists. With parameters, your methods become much more versatile. Instead of getting the same thing each time, you can send somebody to the supermarket to buy bread one time, bananas another time, and birdseed the third time. When you call your goToTheSupermarketAndBuySome method, you decide right there and then what you’re going to ask your pal to buy.

These concepts are made more concrete in Listings 19-6 and 19-7.

Listing 19-6: Adding Interest

import java.text.NumberFormat;

import static java.lang.System.out;

class NiceAccount {

    String lastName;

    int id;

    double balance;

    void addInterest(double rate) {

        out.print(“Adding “);  

        out.print(rate);

        out.println(“ percent...”);

        

        balance += balance * (rate / 100.0);

    }

    void display() {

        NumberFormat currency =

            NumberFormat.getCurrencyInstance();

            

        out.print(“The account with last name “);

        out.print(lastName);

        out.print(“ and ID number “);

        out.print(id);

        out.print(“ has balance “);

        out.println(currency.format(balance));

    }

}

Listing 19-7: Calling the addInterest Method

import java.util.Random;

class ProcessNiceAccounts {

    

    public static void main(String args[]) {

        Random myRandom = new Random();

        NiceAccount anAccount;

        double interestRate;

        for (int i = 0; i < 3; i++) {

            anAccount = new NiceAccount();

            anAccount.lastName = “” +

                (char) (myRandom.nextInt(26) + ‘A’) +

                (char) (myRandom.nextInt(26) + ‘a’) +

                (char) (myRandom.nextInt(26) + ‘a’);        

            anAccount.id = myRandom.nextInt(10000);

            anAccount.balance = myRandom.nextInt(10000);

            anAccount.display();

            

            interestRate = myRandom.nextInt(5);

            anAccount.addInterest(interestRate);

            anAccount.display();

            System.out.println();

        }

    }

}

In Listing 19-7, the line

anAccount.addInterest(interestRate);

plays the same role as the line goToTheSupermarketAndBuySome(bread) in my little supermarket example. The word addInterest is a method name, and the word interestRate in parentheses is a parameter. Taken as a whole, this statement tells the code in Listing 19-6 to execute its ­addInterest method. This statement also tells Listing 19-6 to use a certain number (whatever value is stored in the interestRate variable) in the method’s calculations. The value of interestRate can be 1.0, 2.0, or whatever other value you get by calling myRandom.nextInt(5). In the same way, the goToTheSupermarketAndBuySome method works for bread, bananas, or whatever else you need from the market.

The next section has a detailed description of addInterest and its action. In the meantime, a run of the code in Listings 19-6 and 19-7 is shown in Figure 19-5.

Figure 19-5: Running the code in Listing 19-7.

9780470371749-fg1905.tif

remember.eps Java has very strict rules about the use of types. For example, you can’t assign a double value (like 3.14) to an int variable. (The compiler simply refuses to chop off the .14 part. You get an error message. So what else is new?) But Java isn’t completely unreasonable about the use of types. Java allows you to assign an int value (like myRandom.nextInt(5)) to a double variable (like interestRate). If you assign the int value 2 to the double variable interestRate, then the value of interestRate becomes 2.0. The result is shown on the second line of Figure 19-5.

Handing off a value

When you call a method, you can pass information to that method on the fly. This information is in the method’s parameter list. Listing 19-7 has a call to the addInterest method:

anAccount.addInterest(interestRate);

The first time through the loop, the value of interestRate is 2.0. (Remember, I’m using the data in Figure 19-5.) So at that point in the program’s run, the method call behaves as if it’s the following statement:

anAccount.addInterest(2.0);

The computer is about to run the code inside the addInterest method (a method in Listing 19-6). But first, the computer passes the value 2.0 to the parameter in the addInterest method’s header. So inside the ­addInterest method, the value of rate becomes 2.0. For an illustration of this idea, see Figure 19-6.

Here’s something interesting. The parameter in the addInterest method’s header is rate. But, inside the ProcessNiceAccounts class, the parameter in the method call is interestRate. That’s okay. In fact, it’s standard practice.

Figure 19-6: Passing a value to a method’s parameter.

9780470371749-fg1906.tif

In Listings 19-6 and 19-7, the names of the parameters don’t have to be the same. The only thing that matters is that both parameters (rate and ­interestRate) have the same type. In Listings 19-6 and 19-7, both of these parameters are of type double. So everything is fine.

Inside the addInterest method, the += assignment operator adds balance * (rate / 100.0) to the existing balance value. For some info about the += assignment operator, see Chapter 7.

Working with a method header

In the next few bullets, I make some observations about the addInterest method header (in Listing 19-6):

check.png The word void tells the computer that when the addInterest method is called, the addInterest method doesn’t send a value back to the place that called it.

The next section has an example in which a method sends a value back.

check.png The word addInterest is the method’s name.

That’s the name you use to call the method when you’re writing the code for the ProcessNiceAccounts class (see Listing 19-7).

check.png The parentheses in the header contain placeholders for all the things you’re going to pass to the method when you call it.

When you call a method, you can pass information to that method on the fly. This information is the method’s parameter list. The ­addInterest method’s header says that the addInterest method takes one piece of information, and that piece of information must be of type double:

void addInterest(double rate)

Sure enough, if you look at the call to addInterest (down in the ProcessNiceAccounts class’s main method), that call has the variable interestRate in it. And interestRate is of type double. When I call getInterest, I’m giving the method a value of type double.

How the method uses the object’s values

The addInterest method in Listing 19-6 is called three times from the main method in Listing 19-7. The actual account balances and interest rates are different each time:

check.png In the first call of Figure 19-5, the balance is 8983.00, and the interest rate is 2.0.

When this call is made, the expression balance * (rate / 100.0) stands for 8983.00 * (2.0 / 100.00). See Figure 19-7.

check.png In the second call of Figure 19-5, the balance is 3756.00, and the interest rate is 0.0.

When the call is made, the expression balance * (rate / 100.0) stands for 3756.00 * (0.0 / 100.00). Again, see Figure 19-7.

check.png In the third call of Figure 19-5, the balance is 8474.00, and the interest rate is 3.0.

When the addInterest call is made, the expression balance * (rate / 100.0) stands for 8474.00 * (3.0 / 100.00).

Figure 19-7: Cbj’s account and Bry’s account.

9780470371749-fg1907.tif

Getting a Value from a Method

Say that you’re sending a friend to buy groceries. You make requests for groceries in the form of method calls. You issue calls such as

goToTheSupermarketAndBuySome(bread);

goToTheSupermarketAndBuySome(bananas);

The things in parentheses are parameters. Each time you call your ­goToTheSupermarketAndBuySome method, you put a different value in the method’s parameter list.

Now what happens when your friend returns from the supermarket? “Here’s the bread you asked me to buy,” says your friend. As a result of carrying out your wishes, your friend returns something to you. You made a method call, and the method returns information (or better yet, the method returns some food).

The thing returned to you is called the method’s return value, and the type of thing returned to you is called the method’s return type.

An example

To see how return values and a return types work in a real Java program, check out the code in Listings 19-8 and 19-9.

Listing 19-8: A Method That Returns a Value

import java.text.NumberFormat;

import static java.lang.System.out;

class GoodAccount {

    String lastName;

    int id;

    double balance;

    double getInterest(double rate) {

        double interest;

        

        out.print(“Adding “);  

        out.print(rate);

        out.println(“ percent...”);

        

        interest = balance * (rate / 100.0);

        return interest;

    }

    void display() {

        NumberFormat currency =

            NumberFormat.getCurrencyInstance();

            

        out.print(“The account with last name “);

        out.print(lastName);

        out.print(“ and ID number “);

        out.print(id);

        out.print(“ has balance “);

        out.println(currency.format(balance));

    }

}

Listing 19-9: Calling the Method in Listing 19-8

import java.util.Random;

import java.text.NumberFormat;

class ProcessGoodAccounts {

    

    public static void main(String args[]) {

        Random myRandom = new Random();

        NumberFormat currency =

            NumberFormat.getCurrencyInstance();

        GoodAccount anAccount;

        double interestRate;

        double yearlyInterest;

        for (int i = 0; i < 3; i++) {

            anAccount = new GoodAccount();

            anAccount.lastName = “” +

                (char) (myRandom.nextInt(26) + ‘A’) +

                (char) (myRandom.nextInt(26) + ‘a’) +

                (char) (myRandom.nextInt(26) + ‘a’);        

            anAccount.id = myRandom.nextInt(10000);

            anAccount.balance = myRandom.nextInt(10000);

            anAccount.display();

            interestRate = myRandom.nextInt(5);

            yearlyInterest =

                anAccount.getInterest(interestRate);

            System.out.print(“This year’s interest is “);

            System.out.println

                (currency.format(yearlyInterest));

            System.out.println();

        }

    }

}

To see a run of code from Listings 19-8 and 19-9, take a look at Figure 19-8.

Figure 19-8: Running the code in Listing 19-9.

9780470371749-fg1908.tif

How return types and return values work

I want to trace a piece of the action in Listings 19-8 and 19-9. For input data, I use the first set of values in Figure 19-8.

Here’s what happens when getInterest is called (you can follow along in Figure 19-9):

check.png The value of balance is 9508.00, and the value of rate is 2.0. So the value of balance * (rate / 100.0) is 190.16 — one-hundred ninety dollars and sixteen cents.

check.png The value 190.16 gets assigned to the interest variable, so the ­statement

return interest;

has the same effect as

return 190.16;

check.png The return statement sends this value 190.16 back to the code that called the method. At that point in the process, the entire method call in Listing 19-9anAccount.getInterest(interestRate)takes on the value 190.16.

check.png Finally, the value 190.16 gets assigned to the variable yearlyInterest.

remember.eps If a method returns anything, then a call to the method is an expression with a value. That value can be printed, assigned to a variable, added to something else, or whatever. Anything you can do with any other kind of value, you can do with a method call.

Figure 19-9: A method call is an expression with a value.

9780470371749-fg1909.tif

Working with the method header (again)

When you create a method or a method call, you have to be careful to use Java’s types consistently. So make sure that you check for the following:

check.png In Listing 19-8, the getInterest method’s header starts with the word double. So when the method is executed, it should send a double value back to the place that called it.

check.png Again in Listing 19-8, the last statement in the getInterest method is return interest. So the method returns whatever value is stored in the interest variable, and the interest variable has type double. So far, so good.

check.png In Listing 19-9, the value returned by the call to getInterest is assigned to a variable named yearlyInterest. Sure enough, yearlyInterest is of type double.

That settles it! The use of types in the handling of method getInterest is consistent in Listings 19-8 and 19-9. I’m thrilled!