Chapter VII Creating Class Methods Chapter VII Topics 7.1 Introduction 7.2 The Math Class Revisited 7.3 Modular Programming and Creating Simple Methods 7.4 Graphics Programs with Multiple Methods 7.5 Creating a Big Graphics Program Step-By-Step 7.6 Void Methods with a Single Parameter 7.7 Void Methods with Multiple Parameters 7.8 Return Methods with a Single Parameter 7.9 Return Methods with Multiple Parameters 7.10 Introduction to Program Design 7.11 Creating Methods with Other Methods 7.12 Making a Utility Library Class 7.13 Summary Chapter VII Creating Class Methods 279 7.1 Introduction Chapter IV introduced a few Object Oriented Programming (OOP) concepts. In particular, emphasis was placed on using class methods. You learned that an object is capable of containing both data, often called attributes, and action modules that can process data, called methods. The lion's share of the Chapter IV revolved around using methods of existing classes. Later you also learned the difference between calling class methods with the class identifier and object methods with the object identifier. Class methods are normally utility methods that do not access changing data fields. The Math class is a good example of a class where data will not change. There are many methods in the Math class, but only two data fields, PI and E, which do not change. Methods of the Math class are class methods and must be accessed using the Math class identifier. If you want to access the value of PI, you need to use Math.PI in your program. If you want to compute the square root of 100, you need Math.sqrt(100) in your program. It is a different story when you have the need to use methods with different sets of data. In this case, a new and separate object needs to be constructed for every variable. Most classes require variables for many different data storage situations. In the last chapter you saw the Bank class. That is a good example of a class, which requires multiple objects, one for each customer of the Bank class. Here is an example of using the Bank class: Bank tom = new Bank(); tom.checkingDeposit(1000); System.out.println(tom.getChecking); The point that is being made here is that if you want to call an object method, an object must be created, and you need to use the name of the object in order to call the method. In the statement int num; int is the data type and num is the variable. Likewise in the statement Bank tom; Bank is the data type and tom is the variable. There is a very important distinction between simple data types (or primitive data types) like int, double, and char, and complex data types like Bank and Random. A simple/primitive data type can store only one single value. This means an int can only store one integer. A double can only store one real number. A char can only store one character. On the other hand, a class is a complex data type. An object is a complex variable that can store multiple pieces of information (class attributes) as well as several methods (class actions). 280 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 As you saw examples of class methods and object methods, you also learned that methods can have one or more parameters or arguments. Parameters provide information to methods for processing. Additionally, methods fall into two major categories, which are return methods and void methods. Return methods return some requested value, like the tom.getChecking(); statement, which returns the checking account balance of the object tom. Void methods do not return any values. That is why they are called void methods… because their return date type is void. Void methods frequently alter object data, like the statement: tom.checkingDeposite(1000.0); which adds $1000.00 to the checking account balance of the tom object. Now and then we have students ask, “Mr. Schram, are object methods void or return methods?” What you need to realize is that the whole class method vs. object method thing has nothing to do with the whole void method vs. return method thing. Let us spell it out plainly: 1. 2. 3. 4. A method can be BOTH a void method and a class method. A method can be BOTH a void method and an object method. A method can be BOTH a return method and a class method. A method can be BOTH a return method and an object method. So there are void class methods, void object methods, return class methods, and return object methods. In this chapter you will learn how to create and write your own class methods and in the next chapter you will learn how to write your own object methods. You have already seen that there is a difference in using or calling class methods and object methods. There is also a difference in writing class methods and object methods. As your programs start to increase in size, it becomes important to consider some proper program design concepts. This chapter will introduce program design with the use of classes. It is not possible to create large, reliable programs without being very conscious of program design. Chapter VII Creating Class Methods 281 7.2 The Math Class Revisited The Math class was used in the last chapter because students have familiarity with the methods of the Math class. Program Java0701.java, in Figure 7.1, calls the majority of the Math methods in one program. This will review how to call class methods and it will also introduce various Math methods that were not shown in the earlier chapter. It is possible that some of these math functions are not familiar to you. You will learn about them in Algebra II and Pre-Calculus. Additional Math Methods (not previously shown in Chapter 4) Math.log10(p) returns the log base 10 of p Math.log(p) returns the natural log (base e) of p Math.exp(p) returns the antilog of the p or ep Math.sin(p) returns the trigonometric sine of p Math.cos(p) returns the trigonometric cosine of p Math.tan(p) returns the trigonometric tangent of p Math.asin(p) returns the trigonometric arcsine of p Math.acos(p) returns the trigonometric arccosine of p Math.atan(p) returns the trigonometric arctangent of p Math.toDegrees(p) returns the number of degrees in p radians Math.toRadians(p) returns the number of radians in p degrees Figure 7.1 // Java0701.java // This program reviews using class methods and demonstrates the // available <Math> class methods and data fields. public class Java0701 { public static void main (String args[]) { double halfPI = Math.PI / 2; double quarterPI = Math.PI / 4; System.out.println("The value of E is System.out.println("The value of PI is System.out.println("The absolute value of (-25) is System.out.println("The square root of (1024) is System.out.println("(5.00001) rounded up is System.out.println("(5.99999) rounded down is 282 " + Math.E); " + Math.PI); " + Math.abs(-25)); " + Math.sqrt(1024)); " + Math.ceil(5.00001)); " + Math.floor(5.99999)); Exposure Java 2014 for teaching AP®CS Edition 07-25-14 System.out.println("(5.50001) rounded normally is System.out.println("(5.49999) rounded normally is System.out.println("The log base 10 of (100) is System.out.println("The natural log of (100) is System.out.println("The antilog of (4.605170185988092) is System.out.println("With (1000,999) the greater number is System.out.println("With (1000,999) the lesser number is System.out.println("4 to the 3rd power is System.out.println("3 to the 4th power is System.out.println("The sine of (PI/2) is System.out.println("The cosine of (PI) is System.out.println("The tangent of (PI/4) is System.out.println("The arcsine of (1) is System.out.println("The arccosine of (-1) is System.out.println("The arctangent of (1) is System.out.println("(PI) radians equals System.out.println("(180) degrees equals System.out.println("A random real number between 0 & 1 is System.out.println("Another random real# between 0 & 1 is System.out.println(); " + Math.round(5.50001)); " + Math.round(5.49999)); " + Math.log10(100)); " + Math.log(100)); " + Math.exp(4.605170185988092)); " + Math.max(1000,999)); " + Math.min(1000,999)); " + Math.pow(4,3)); " + Math.pow(3,4)); " + Math.sin(halfPI)); " + Math.cos(Math.PI)); " + Math.tan(quarterPI)); " + Math.asin(1)); " + Math.acos(-1)); " + Math.atan(1)); " + Math.toDegrees(Math.PI) + " degrees"); " + Math.toRadians(180) + " radians"); " + Math.random()); " + Math.random()); } } Figure 7.1 Continued The value of E is The value of PI is The absolute value of (-25) is The square root of (1024) is (5.00001) rounded up is (5.99999) rounded down is (5.50001) rounded normally is (5.49999) rounded normally is The log base 10 of (100) is The natural log of (100) is The antilog of (4.605170185988092) is With (1000,999) the greater number is With (1000,999) the lesser number is 4 to the 3rd power is 3 to the 4th power is The sine of (PI/2) is The cosine of (PI) is The tangent of (PI/4) is The arcsine of (1) is The arccosine of (-1) is The arctangent of (1) is (PI) radians equals (180) degrees equals A random real number between 0 & 1 is Another random real# between 0 & 1 is 2.718281828459045 3.141592653589793 25 32.0 6.0 5.0 6 5 2.0 4.605170185988092 100.00000000000004 1000 999 64.0 81.0 1.0 -1.0 0.9999999999999999 1.5707963267948966 3.141592653589793 0.7853981633974483 180.0 degrees 3.141592653589793 radians 0.7844904826995998 0.272599238665994 Chapter VII Creating Class Methods 283 7.3 Modular Programming and Creating Simple Methods Near the end of this chapter you will see an example of a very poorly written program, which is then slowly improved with many stages of program design. The title of this chapter is User Created Methods, but the creation of special modules, called methods, is motivated by program design. In other words, this chapter will introduce many introductory program design features. One important program design feature is modular programming. It is possible to write a program with hundreds and even thousands of lines of program code that are all shoved into a single main or paint method. Such a program may work correctly, but making any fixes or changes to the program will be very difficult. Imagine the following program. Your program draws a very beautiful horse. This horse requires around 5000 program statements. Now suppose that you have a gorgeous horse, but the tail is wrong. Fixing the tail problem is difficult with many program statements bunched together. On the other hand, if you had created many small modules for each part of the horse, making changes is simple. If any group of related statements is placed in its own module, called a method in Java, then you have taken an important step in designing your program. Another terrific benefit is that methods have a name or identifier. Perhaps the tail requires fifty lines of programming. Place each one of those statements into one module and call the module drawTail. Any future programming that needs to fix or improve the tail is now simpler. Look for the method called drawTail and you can get started without tedious searching through program statements. This business of combining common statements into their own modules is called Modular Programming with the philosophy: One task, one module. Modular Programming Modular programming is the process of placing statements that achieve a common purpose into its own module. An old programming saying says it well One Task, One Module 284 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Using modular programming will start with a very simple program that displays a mailing address. There is nothing complicated about this program and there is nothing that demonstrates how to create methods. Program Java0702.java, in Figure 7.2, shows a program that displays a mailing address and will be used to introduce the process of creating Java subroutines or methods. This program has only one method, which is the main method that you have used since the first Java program. You certainly have used classes and methods since Unit-2, but all those methods already exist in Java. Now you will learn to create your very own classes and methods. Figure 7.1 // Java0702.java // This program displays a simple mailing address. // It will be used to demonstrate how to divide program sections of // the main method into multiple user-created methods. public class Java0702 { public static void main(String[] args) { System.out.println("Kathy Smith"); System.out.println("7003 Orleans Court"); System.out.println("Kensington, Md. 20795"); } } Kathy Smith 7003 Orleans Court Kensington, Md. 20795 When you look at this program do take a closer look at the main method. It starts with a heading that includes the method name main. Then there is a set of braces that contain the program statements of the method. The entire method, heading and method body together are inside another container called a class. In this case that is the Java0701 class. Notice that the class also has a heading with a name and then a set of braces. With that information we can move on and create our own methods. Please realize that whether a class or method is already provided by Java or you create the class and method, the process is identical. Up to this point, every program you have worked with has had exactly one method. If it was an application, it was the main method. If it was an applet, it was the paint method. Consider the name of the “main” method. If you have a main or primary method, would that not imply the existence of other secondary methods? The answer is “yes” as the next several programs will demonstrate. Chapter VII Creating Class Methods 285 Program Java0703.java, in Figure 7.3, creates the exact same mailing address as the previous program. This time there are three other methods in the program besides the main method. The previous address program statements have been placed in three methods, called fullName, street and cityStateZip. Each of these new methods is user-created. Please observe that each method has a heading that follows the same format as the main method. The heading starts with public static void followed by the method name fullName, etc. Once again there is a set of braces { } which contain the method body of program statements. When you execute a program with multiple methods, where does it start? It starts with the main method. This is why it is called the main method in the first place. The main method is now used to call each one of the new methods in sequence. Make sure that you do not add a semicolon at the end of the method heading. Yes, you are told that every program statement ends with a semi-colon, but a method heading, class heading or loop heading is not a program statement and thus does not get a semi-colon. When you look inside the main method you will see the three method calls. Now, you have called methods before, and you have always used the class-dotmethod format when doing so. For example, how do you call the sqrt method from the Math class? You use Math.sqrt. You use the class identifier (name of the class), followed by a period, followed by the method identifier (name of the method). Calling methods that you have created yourself is no different from calling other methods. In this program, the name of the class is Java0703. The names of the methods I want to call are fullName, street, and cityStateZip. So to call these methods, I need to use the same class-dot-method format. The result is Java0703.fullname(), Java0703.street(), and Java0703.cityStateZip(). Sometimes students will ask why it is necessary to break up such a small program into different methods. It does not seem to be necessary. After all, the first program worked just fine with only the main method. Now, I could include examples of professional software, which absolutely would not work without methods; however, such code is thousands of lines long and more than a bit complex. Please realize the process of breaking a program up into different methods is the same whether each method has 1 program statement or 1000 program statements. Simplistic examples are often used to help the understanding of a concept – not to show examples of real world programs which would overwhelm students in a first year computer science course. 286 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.3 // Java0703.java // This program introduces user-created class methods. // The three program statements of the Java0703.java program // are now divided into three user-created methods. // Each method is called with the class-dot-method format. public class Java0703 { public static void main(String[] args) { Java0703.fullName(); Java0703.street(); Java0703.cityStateZip(); } public static void fullName() { System.out.println("Kathy Smith"); } public static void street() { System.out.println("7003 Orleans Court"); } public static void cityStateZip() { System.out.println("Kensington, Md. 20795"); } } User-Created Method Format A user-defined method requires: A heading, which includes the method name A set of { } braces to contain the method body statements A body of program statements inside the { } braces public static void example() { System.out.println("This is an example of a"); System.out.println("user-defined method"); } Chapter VII Creating Class Methods 287 Program Java0704.java, in Figure 7.4, does exactly the same thing as the previous program. It has the same exact methods. There is one important difference – how the methods are called. If you look at the main method, we are calling the methods without first specifying the name of the class. How does this work? I mean we cannot find the square root of a number with just sqrt. We need Math.sqrt. It is always necessary to first specify the name of the class, and then specify the name of the method… or is it? Think of mailing a letter. If you live in the United States, and you send a letter to someone else in the United States, do you need to include “U.S.A.” in the address? No, you do not because you are already in the United States. What if you did include “U.S.A.” in the address? Would that be a problem? No, it is just extra information. This is essentially what is happening with this program, and the previous one. In program Java0703.java, we can call the fullName, street, and cityStateZip methods without using the name of the class because all of these methods are in the same class as the main method. So this is the one exception to the class-dotmethod rule. If both the method you are calling, and the method you are calling from (usually the main method) are in the same class, you do not need to use the name of the class. You still can if you really want to – like in program Java0703.java – but it is not necessary. Figure 7.4 // Java0704.java // This program example displays the same output as the previous program. // This time the methods are called without using the name of the class. // Omitting the class identifier is possible because all the methods are // in the same class, <Java0704>. public class Java0704 { public static void main(String[] args) { fullName(); street(); cityStateZip(); } public static void fullName() { System.out.println("Kathy Smith"); } public static void street() { System.out.println("7003 Orleans Court"); } public static void cityStateZip() 288 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 { System.out.println("Kensington, Md. 20795"); } } The previous two programs placed each of the new methods inside the same class as the main method. Program Java0705.java, in Figure 7.5, creates a userdefined Address class and places the three new methods inside the second class. Figure 7.5 // Java0705.java // This program demonstrates how to use a second class separate // from the main program class. // This program will not compile, because the <fullName>, <street> // and <cityStateZip> methods are no longer contained in the <Java0704> class. public class Java0705 { public static void main(String args[]) { fullName(); street(); cityStateZip(); } } class Address { public static void fullName() { System.out.println("Kathy Smith"); } public static void street() { System.out.println("7003 Orleans Court"); } public static void cityStateZip() { System.out.println("Kensington, Md. 20795"); } } Chapter VII Creating Class Methods 289 A class is considered a toolkit and methods are considered tools. A well-designed program creates separate classes to contain a common set of methods designed for a similar purpose. In the case of Java0705.java all three of the methods are involved with the display of a mailing address. It makes sense to place these three methods inside a common class, called Address. It is all very nice, but Figure 7.6 shows that the Java compiler is not happy and generates three errors at compile time. Each of the errors indicates that Java cannot find the three new methods. The previous program had no difficulty, but then the new methods were in the same container as the main method. A program statement in one class cannot call a method in another class using only the method name. Figure 7.6 Think again about the “mail” analogy that I used earlier. What if you were on vacation in Rome and you were mailing a letter to a friend in the United States? In that case you must include U.S.A. in the address. It is a good idea and it is considered good program design, to place common purpose methods inside their own class container. You just need to make sure that you include the class name with the method name when such methods are used. Program Java0706.java, in Figure 7.7, has the exact same Address class, but this time you will see in the main method that each method call starts with the class name Address. We are again using the proper class-dot-method format. 290 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.7 // Java0706.java // This program cures the problem of the previous program. // It is possible to declare multiple classes in one program, // but you must use the class-dot-method format to call // any of the <Address> class methods. public class Java0706 { public static void main(String args[]) { Address.fullName(); Address.street(); Address.cityStateZip(); } } class Address { public static void fullName() { System.out.println("Kathy Smith"); } public static void street() { System.out.println("7003 Orleans Court"); } public static void cityStateZip() { System.out.println("Kensington, Md. 20795"); } } Kathy Smith 7003 Orleans Court Kensington, Md. 20795 Chapter VII Creating Class Methods 291 Using the Class Identifier The name of the class is called the class identifier. Using the class identifier is optional if you are calling a method that is in the same class. Using the class identifier is required if you are calling a method that is in a different class. The past couple programs have something new that you have not seen before. They each contain more than one class. Declaring a second class in a Java file is not a problem. The syntax of a second class is almost identical to the primary class with one important distinction. A second and third class, placed in the same file, should not be declared public. Only the primary class, the one with the same name as the file, is public. This brings up one of the first rules you learned in Java programming. Here it is again, just in case you forgot: File Names and Class Names The external file name of your program must be identical to the public class name inside your program, minus the java extension. For example: If you use public class Howdy in your program then you must save the program with file name Howdy.java Have you ever wondered why Java has this rule? The reason is finally demonstrated in the next program. Program Java0707.java, in Figure 7.8, starts off the same way as the previous program… but there is no Address class. Surely such a program cannot possibly compile. Go ahead and try. Amazingly, it does compile and has the exact same output as the previous program. Figure 7.8 // Java0707.java // In this program, the <Address> class is in the file Address.java // If the compiler does not find a class it needs in this file, // if will look for it in a .java file with the same name. // This is the whole reason why the name of the file must match the // name of the public class. // NOTE: This class contains the <main> method. 292 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 // // That makes this the "Driving Class" of the program. That means this is the file that needs to be compiled and executed. public class Java0707 { public static void main(String args[]) { Address.fullName(); Address.street(); Address.cityStateZip(); } } Kathy Smith 7003 Orleans Court Kensington, Md. 20795 So how is this possible? How can this program execute the statement Address.fullName(); when there is no fullName method in the program. There is no Address class at all! Well, technically, there is… you just are just looking in the wrong place. We have mentioned that it is good programming practice to break up a program into different methods and to group like methods in the same class. The next step in good program design is to put each class in its own file. This is what was done in this program. The Address class was placed in the file Address.java as shown in Figure 7.9. Note that Address is now declared as a public class. This is because it is in its own file. Figure 7.9 // Address.java // This is the <Address> class used by Java0707.java // NOTE: Now that <Address> is in its own file, it must be declared <public>. // ALSO: This file can be compiled, but since it has not <main> method, it cannot be executed. public class Address { public static void fullName() { System.out.println("Kathy Smith"); } public static void street() { System.out.println("7003 Orleans Court"); } Chapter VII Creating Class Methods 293 public static void cityStateZip() { System.out.println("Kensington, Md. 20795"); } } OK, fine, but when the Java compiler encountered the statement Address.fullName(); how did it know to look for the Address class in the file Address.java? It knew because that file has the same name as the class. This is the whole reason that rule exists. NOTE: While it is proper programming style to put each class in its own file, most program examples in this textbook will continue to put all classes in the same file for simplicity. 7.4 Graphics Programs with Multiple Methods All of the examples that we have seen so far have been text programs, but what about graphics programs? Program Java0708.java, in Figure 7.10, is a graphics program that draws a house. If you were to compare this program to the very first program in this chapter you would find few similarities. One is a text application; the other is a graphics applet. Their outputs are certainly different. They are similar in one very important way. Both programs have all of the program statements in a single method. Program Java0702.java has all of the program statements in the main method, and program Java0708.java has all of the program statements in the paint method. Both programs use poor program design. Figure 7.10 // Java0708.java // This program draws a house by placing all the necessary // program statements inside the <paint> method. // This is an example of poor program design. import java.awt.*; import java.applet.*; public class Java0708 extends Applet { 294 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 public void paint(Graphics g) { g.setColor(Color.blue); g.drawRect(200,200,300,100); g.drawRect(200,300,300,100); g.setColor(Color.red); g.drawLine(200,200,350,100); g.drawLine(500,200,350,100); g.drawLine(200,200,500,200); g.setColor(Color.red); g.drawLine(420,146,420,80); g.drawLine(420,80,450,80); g.drawLine(450,80,450,166); g.setColor(Color.black); g.drawRect(330,340,40,60); g.drawOval(340,350,20,40); g.fillOval(364,370,5,5); g.setColor(Color.black); g.drawRect(220,220,60,60); g.drawLine(220,250,280,250); g.drawLine(250,220,250,280); g.drawRect(420,220,60,60); g.drawLine(420,250,480,250); g.drawLine(450,220,450,280); g.drawRect(320,220,60,60); g.drawLine(320,250,380,250); g.drawLine(350,220,350,280); g.drawRect(220,320,60,60); g.drawLine(220,350,280,350); g.drawLine(250,320,250,380); g.drawRect(420,320,60,60); g.drawLine(420,350,480,350); g.drawLine(450,320,450,380); } } Figure 7.10 Continued Chapter VII Creating Class Methods 295 You may still not appreciate what the point is here. Imagine that you do not like the appearance of the chimney. Where in the paint method do you go to make the changes? It is not really that easy to see. I hope you understand that the house displayed in Figure 7.10 can easily be made far more complex with thousands of program statements. Just imagine if the house includes actual bricks, bushes, plants in the windows, a number on the doors, Christmas lights, and kids playing in the yard. In no time a project as the one described requires more than 1000 program statements. Placing all those statements in one single paint method is very poor program design. Making any changes becomes very tedious. Even with this relatively small program could you tell just by the program statements that they will draw a house? Sometimes when students work on a program that contains too many lines in one module, they argue that they know the purpose of each program statement. This is quite true when the program writing is fresh in your mind. It is a different story when time goes by. We wrote an Academic Decathlon program of about 12,000 lines about twenty years ago. We were in a hurry to meet a deadline. The program lacked proper modular program design and comments were pretty much non-existent. In the heat of writing the program day after day, we stayed on top of everything. Then we received a wake-up call one year later. It was a program for Academic Decathlon data processing and there were major changes. Altering the poorly-designed program a year later was a nightmare. Accept it. The rules of “Proper Programming Design” are important. Imagine you need to write a major research paper for English class. Do you begin by typing the final copy? Hopefully not. Most English teachers will require you to first turn in an outline. It is similar with a program. If I want to draw a house, I would start by asking myself “What is needed to draw a house?” I would then answer myself, “A house has a door, roof, chimney, windows and (since this will be a 2-story house) a couple floors. Now look at program Java0709.java, in Figure 7.11. You will see that the house program is now divided up into 5 different methods: drawFloors, drawRoof, drawDoor, drawWindows and drawChimney. Look closely at the paint method. Doesn’t it look like an outline? This is what a paint method or a main method is supposed to look like in a well-designed program. Note that all of these methods have the same Graphics g in their heading as the paint method. If you look at the method calls in the paint method, you will see that they pass the Graphics object g as a parameter. NOTE: User-Defined parameters will be discussed in great detail later in the chapter. 296 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.11 // Java0709.java // This program organizes all the program statements // of the previous program into six separate methods. // This is better program design. It is now easier to debug and alter the program. import java.awt.*; import java.applet.*; public class Java0709 extends Applet { public void paint(Graphics g) { drawFloors(g); drawRoof(g); drawDoor(g); drawWindows(g); drawChimney(g); } public static void drawFloors(Graphics g) { g.setColor(Color.blue); g.drawRect(200,200,300,100); g.drawRect(200,300,300,100); } public static void drawRoof(Graphics g) { g.setColor(Color.red); g.drawLine(200,200,350,100); g.drawLine(500,200,350,100); g.drawLine(200,200,500,200); } public static void drawDoor(Graphics g) { g.setColor(Color.black); g.drawRect(330,340,40,60); g.drawOval(340,350,20,40); g.fillOval(364,370,5,5); } public static void drawWindows(Graphics g) { g.setColor(Color.black); g.drawRect(220,220,60,60); g.drawLine(220,250,280,250); g.drawLine(250,220,250,280); g.drawRect(420,220,60,60); g.drawLine(420,250,480,250); g.drawLine(450,220,450,280); g.drawRect(320,220,60,60); Chapter VII Creating Class Methods 297 g.drawLine(320,250,380,250); g.drawLine(350,220,350,280); g.drawRect(220,320,60,60); g.drawLine(220,350,280,350); g.drawLine(250,320,250,380); g.drawRect(420,320,60,60); g.drawLine(420,350,480,350); g.drawLine(450,320,450,380); } public static void drawChimney(Graphics g) { g.setColor(Color.red); g.drawLine(420,146,420,80); g.drawLine(420,80,450,80); g.drawLine(450,80,450,166); } } Consider the chimney question that was asked with the previous program. If this program’s chimney had issues you would go to the drawChimney method to fix it. If you did not like the windows, you would go to drawWindows. Having methods with self-commenting names makes debugging and enhancing your programs much easier. If we are going to continue the pattern of the previous section, then after we break the program up into different methods, we should group the like methods in their own class. We now have 5 methods that are all used to draw a house. Program Java0710.java, in Figure 7.12, takes these 5 methods and places them all inside a House class. Take note that calling these five methods must now be preceded by using the House identifier. Figure 7.12 // Java0710.java // This program places the five methods from the previous program // into their own <House> class, which is even better program design. import java.awt.*; import java.applet.*; public class Java0710 extends Applet { public void paint(Graphics g) { House.drawFloors(g); House.drawRoof(g); House.drawDoor(g); House.drawWindows(g); House.drawChimney(g); } } 298 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 class House { public static void drawFloors(Graphics g) { g.setColor(Color.blue); g.drawRect(200,200,300,100); g.drawRect(200,300,300,100); } public static void drawRoof(Graphics g) { g.setColor(Color.red); g.drawLine(200,200,350,100); g.drawLine(500,200,350,100); g.drawLine(200,200,500,200); } public static void drawDoor(Graphics g) { g.setColor(Color.black); g.drawRect(330,340,40,60); g.drawOval(340,350,20,40); g.fillOval(364,370,5,5); } public static void drawWindows(Graphics g) { g.setColor(Color.black); g.drawRect(220,220,60,60); g.drawLine(220,250,280,250); g.drawLine(250,220,250,280); g.drawRect(420,220,60,60); g.drawLine(420,250,480,250); g.drawLine(450,220,450,280); g.drawRect(320,220,60,60); g.drawLine(320,250,380,250); g.drawLine(350,220,350,280); g.drawRect(220,320,60,60); g.drawLine(220,350,280,350); g.drawLine(250,320,250,380); g.drawRect(420,320,60,60); g.drawLine(420,350,480,350); g.drawLine(450,320,450,380); } public static void drawChimney(Graphics g) { g.setColor(Color.red); g.drawLine(420,146,420,80); g.drawLine(420,80,450,80); g.drawLine(450,80,450,166); } } Chapter VII Creating Class Methods 299 What happens if you are drawing more than a house? What if the house has a tree in the front yard? Program Java0711.java, in Figure 7.13, adds a Tree class to this program. This is a rather simple tree with a brown rectangle for a trunk and a green circle for the leaves, but it should demonstrate how multiple classes can be used in a program. Note that in the paint method there are calls to Tree.drawTrunk(g); and Tree.drawLeaves(g); both indicating that these are methods of the Tree class. Figure 7.13 // Java0711.java // This program shows that a program can consist of multiple classes, // each of which containing multiple methods. import java.awt.*; import java.applet.*; public class Java0711 extends Applet { public void paint(Graphics g) { House.drawFloors(g); House.drawRoof(g); House.drawDoor(g); House.drawWindows(g); House.drawChimney(g); Tree.drawTrunk(g); Tree.drawLeaves(g); } } class House { // same as the previous program } class Tree { public static void drawTrunk(Graphics g) { g.setColor(new Color(150,100,15)); // brown g.fillRect(700,400,50,200); } public static void drawLeaves(Graphics g) { g.setColor(Color.green); g.fillOval(620,195,210,210); } } 300 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.12 Continued Suppose we want to add a simple background to this program. Program Java0712.java, in Figure 7.14, adds the Background class with drawSky and drawGrass methods. When you run the program, you will no longer see the house and tree. The House and Tree methods are still in the program and technically they were drawn. You do not see them because the background was drawn on top of them. This happened because the background was drawn after the house and the tree. This is a common mistake made by students who sometimes argue that their program should work because the Background class is before the House and Tree classes in the program. What must be understood is that the order of the classes is completely irrelevant. The only thing that matters is the order of the method calls in the main or paint methods. If you look at the paint method, you will see that drawSky (which draws a big dark blue rectangle covering the top half of the screen) and drawGrass (which draws a big dark green rectangle covering the lower half of the screen) are called last. Figure 7.14 // Java0712.java // This program adds a <Background> class to draw the "sky" and "grass". // When you run the program, all you see is the background. // This is because the background was drawn after, and therefore on top of // everything else. Chapter VII Creating Class Methods 301 import java.awt.*; import java.applet.*; public class Java0712 extends Applet { public void paint(Graphics g) { House.drawFloors(g); House.drawRoof(g); House.drawDoor(g); House.drawWindows(g); House.drawChimney(g); Tree.drawTrunk(g); Tree.drawLeaves(g); Background.drawSky(g); Background.drawGrass(g); } } class Background { public static void drawSky(Graphics g) { g.setColor(new Color(128,128,255)); // light blue g.fillRect(0,0,1000,325); } public static void drawGrass(Graphics g) { g.setColor(new Color(0,128,0)); // dark green g.fillRect(0,325,1000,650); } } class House { // same as the previous program } class Tree { // same as the previous program } 302 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.13 Continued Program Java0713.java, in Figure 7.15, fixes the problem of the previous program by calling the 2 Background methods first before anything else is drawn. The house and the tree are drawn next, and therefore on top of the background. While the tree looks fine, there is one remaining problem with the house. It is transparent. You can see both the sky and the grass through the house. This is because unlike the tree, the house is not solid. Figure 7.15 // Java0713.java // This program fixes the issue of the previous program by drawing the background first. // The house does not look right because we can see the background through it. // Unlike the tree, the house is not solid. import java.awt.*; import java.applet.*; public class Java0713 extends Applet { public void paint(Graphics g) { Background.drawSky(g); Background.drawGrass(g); House.drawFloors(g); House.drawRoof(g); Chapter VII Creating Class Methods 303 House.drawDoor(g); House.drawWindows(g); House.drawChimney(g); Tree.drawTrunk(g); Tree.drawLeaves(g); } } // Background, House and Tree classes are the same as the previous program Figure 7.14 Continued Program Java0714.java, in Figure 7.16, changes the methods of the House class so they draw solid shapes. Now the drawing appears as it was intended. Figure 7.16 // Java0714.java // This program changes the methods of the <House> class so they draw solid shapes. // Now the drawing appears as it was intended. import java.awt.*; import java.applet.*; 304 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 public class Java0714 extends Applet { public void paint(Graphics g) { Background.drawSky(g); Background.drawGrass(g); House.drawFloors(g); House.drawRoof(g); House.drawDoor(g); House.drawWindows(g); House.drawChimney(g); Tree.drawTrunk(g); Tree.drawLeaves(g); } } class Background { // same as the previous program } class House { public static void drawFloors(Graphics g) { g.setColor(new Color(231,198,154)); // light tan g.fillRect(200,200,300,200); g.setColor(Color.blue); g.drawRect(200,200,300,100); g.drawRect(200,300,300,100); } public static void drawRoof(Graphics g) { g.setColor(Color.red); Polygon roof = new Polygon(); roof.addPoint(200,200); roof.addPoint(350,100); roof.addPoint(500,200); g.fillPolygon(roof); } public static void drawDoor(Graphics g) { g.setColor(Color.blue); g.fillRect(330,340,40,60); Chapter VII Creating Class Methods 305 g.setColor(Color.black); g.drawRect(330,340,40,60); g.drawOval(340,350,20,40); g.fillOval(364,370,5,5); } public static void drawWindows(Graphics g) { g.setColor(Color.white); g.fillRect(220,220,60,60); g.fillRect(420,220,60,60); g.fillRect(320,220,60,60); g.fillRect(220,320,60,60); g.fillRect(420,320,60,60); g.setColor(Color.black); g.drawRect(220,220,60,60); g.drawLine(220,250,280,250); g.drawLine(250,220,250,280); g.drawRect(420,220,60,60); g.drawLine(420,250,480,250); g.drawLine(450,220,450,280); g.drawRect(320,220,60,60); g.drawLine(320,250,380,250); g.drawLine(350,220,350,280); g.drawRect(220,320,60,60); g.drawLine(220,350,280,350); g.drawLine(250,320,250,380); g.drawRect(420,320,60,60); g.drawLine(420,350,480,350); g.drawLine(450,320,450,380); } public static void drawChimney(Graphics g) { g.setColor(Color.red); Polygon chimney = new Polygon(); chimney.addPoint(420,146); chimney.addPoint(420,80); chimney.addPoint(450,80); chimney.addPoint(450,166); g.fillPolygon(chimney); } } class Tree { // same as the previous program } 306 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.16 Continued If you look at the Programs07 folder, shown in Figure 7.17, it may look like program Java0715.java is missing. It is actually inside the Java0715 subfolder. Figure 7.17 Chapter VII Creating Class Methods 307 The contents of this subfolder are shown in Figure 7.18. Figure 7.18 Program Java0715.java, shown in Figure 7.19, has been split into different files – one for each class. These are shown in Figures 7.20, 7.21 and 7.22. A good way to organize a program made up of different files is to put all of the necessary files in the same folder. Figure 7.19 // Java0715.java // This program has each class in its own file. // It also demonstrates the good organizational practice of // putting all files for a particular program in the same folder. // NOTE: This class contains the <paint> method. // That makes this the "Driving Class" of the program. // That means this is the file that needs to be compiled. import java.awt.*; import java.applet.*; public class Java0715 extends Applet { public void paint(Graphics g) { Background.drawSky(g); Background.drawGrass(g); House.drawFloors(g); House.drawRoof(g); House.drawDoor(g); House.drawWindows(g); House.drawChimney(g); Tree.drawTrunk(g); Tree.drawLeaves(g); } } 308 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.20 // House.java import java.awt.*; import java.applet.*; class House { public static void drawFloors(Graphics g) { g.setColor(new Color(231,198,154)); // light tan g.fillRect(200,200,300,200); g.setColor(Color.blue); g.drawRect(200,200,300,100); g.drawRect(200,300,300,100); } public static void drawRoof(Graphics g) { g.setColor(Color.red); Polygon roof = new Polygon(); roof.addPoint(200,200); roof.addPoint(350,100); roof.addPoint(500,200); g.fillPolygon(roof); } public static void drawDoor(Graphics g) { g.setColor(Color.blue); g.fillRect(330,340,40,60); g.setColor(Color.black); g.drawRect(330,340,40,60); g.drawOval(340,350,20,40); g.fillOval(364,370,5,5); } public static void drawWindows(Graphics g) { g.setColor(Color.white); g.fillRect(220,220,60,60); g.fillRect(420,220,60,60); g.fillRect(320,220,60,60); g.fillRect(220,320,60,60); g.fillRect(420,320,60,60); g.setColor(Color.black); g.drawRect(220,220,60,60); g.drawLine(220,250,280,250); g.drawLine(250,220,250,280); g.drawRect(420,220,60,60); g.drawLine(420,250,480,250); g.drawLine(450,220,450,280); g.drawRect(320,220,60,60); g.drawLine(320,250,380,250); g.drawLine(350,220,350,280); g.drawRect(220,320,60,60); g.drawLine(220,350,280,350); g.drawLine(250,320,250,380); g.drawRect(420,320,60,60); g.drawLine(420,350,480,350); g.drawLine(450,320,450,380); } public static void drawChimney(Graphics g) { g.setColor(Color.red); Polygon chimney = new Polygon(); chimney.addPoint(420,146); Chapter VII Creating Class Methods 309 chimney.addPoint(420,80); chimney.addPoint(450,80); chimney.addPoint(450,166); g.fillPolygon(chimney); } } Figure 7.21 Figure 7.22 // Background.java // Tree.java import java.awt.*; import java.applet.*; import java.awt.*; import java.applet.*; class Background { public static void drawSky(Graphics g) { g.setColor(new Color(128,128,255)); // light blue class Tree { public static void drawTrunk(Graphics g) { g.setColor(new Color(150,100,15)); // brown g.fillRect(0,0,1000,325); g.fillRect(700,400,50,200); } } public static void drawGrass(Graphics g) { g.setColor(new Color(0,128,0)); // dark green public static void drawLeaves(Graphics g) { g.setColor(Color.green); g.fillOval(620,195,210,210); } g.fillRect(0,325,1000,650); } } } Some Program Design Notes Programs should not be written by placing all the program statements in the main or paint methods. Program statements that perform a specific purpose should be placed inside their own modules. These modules are called methods in Java. Object Oriented Design continues by placing methods of a common nature into a separate class. When a program has multiple classes, it is very common to put each class in its own file – one whose name matches the name of the class. 310 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 7.5 Creating a Big Graphics Program Step-By-Step There is a step-by-step process which is used to create programs. It actually works for any program, not just graphics programs. This process will be demonstrated in the next 5 examples. You are STRONGLY advised to use this approach when you create any big program from scratch. Step 1 – Create the paint method. If you were writing a research paper, your teacher would probably require you to first create an outline. We mentioned earlier that in a well-designed program, the main or paint method looks like an outline. So this is a good place to start. Program Java0716.java, shown in Figure 7.23, starts by creating the paint method for a program to draw a house. It should be understood that this first step will not compile. The paint method is trying to call methods drawFloors, drawRoof, drawDoor, drawWindows, and drawChimney -- none of which exist. Figure 7.23 // Java0716.java // Beginning a Big Graphics Program // Step 1 – Create the <paint> method. // This first step will not compile because the program // is attempting to call methods which do not exist. import java.awt.*; import java.applet.*; public class Java0716 extends Applet { public void paint(Graphics g) { drawFloors(g); drawRoof(g); drawDoor(g); drawWindows(g); drawChimney(g); } } Chapter VII Creating Class Methods 311 Figure 7.24 Continued Step 2 – Create Stubs. A stub is a method with a proper heading, but nothing in between the braces { }. Stubs allow a program to compile without actually writing out all of the methods. Program Java0717.java, shown in Figure 7.24 demonstrates that with stubs in place the program can compile, but it has no output. This is because all of the methods are still empty. 312 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.24 // Java0717.java // Beginning a Big Graphics Program // Step 2 – Create Stubs. // Stubs are methods with nothing between the braces { }. // With the stubs in place, the program can compile. import java.awt.*; import java.applet.*; public class Java0717 extends Applet { public void paint(Graphics g) { drawFloors(g); drawRoof(g); drawDoor(g); drawWindows(g); drawChimney(g); } public static void drawFloors(Graphics g) { } public static void drawRoof(Graphics g) { } public static void drawDoor(Graphics g) { } public static void drawWindows(Graphics g) { } public static void drawChimney(Graphics g) { } } Chapter VII Creating Class Methods 313 Figure 7.24 Continued Step 3 – Write the first method and make sure it works. Now that the stubs are in place, you need to pick one of the methods and actually write it. Program Java0718.java, shown in Figure 7.25 demonstrates this by implementing drawDoors. To implement a method means to write the method body which refers to the program statements between the braces { }. Remember to compile and execute to make sure this method works before going on to the next method. Figure 7.25 // Java0718.java // Beginning a Big Graphics Program // Step 3 – Write the first method and make sure it works. import java.awt.*; import java.applet.*; public class Java0718 extends Applet { public void paint(Graphics g) { drawFloors(g); drawRoof(g); drawDoor(g); 314 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 drawWindows(g); drawChimney(g); } public static void drawFloors(Graphics g) { g.setColor(Color.blue); g.drawRect(200,200,300,100); g.drawRect(200,300,300,100); } public static void drawRoof(Graphics g) { } public static void drawDoor(Graphics g) { } public static void drawWindows(Graphics g) { } public static void drawChimney(Graphics g) { } } Figure 7.24 Continued Chapter VII Creating Class Methods 315 Step 4 – Write the next method and make sure it works. With the first method good to go we now move on to the next method. Program Java0719.java, shown in Figure 7.26 demonstrates this by implementing drawRoof. Figure 7.26 // Java0719.java // Beginning a Big Graphics Program // Step 4 – Write the next method and make sure it works. import java.awt.*; import java.applet.*; public class Java0719 extends Applet { public void paint(Graphics g) { drawFloors(g); drawRoof(g); drawDoor(g); drawWindows(g); drawChimney(g); } public static void drawFloors(Graphics g) { g.setColor(Color.blue); g.drawRect(200,200,300,100); g.drawRect(200,300,300,100); } public static void drawRoof(Graphics g) { g.setColor(Color.red); g.drawLine(200,200,350,100); g.drawLine(500,200,350,100); g.drawLine(200,200,500,200); } public static void drawDoor(Graphics g) { } public static void drawWindows(Graphics g) { } public static void drawChimney(Graphics g) { } } 316 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.26 Continued Step 5 – Repeat step 4 until the entire program is done. After a couple methods are done, you just keep repeating the same process by implementing one at a time and testing it before you go on to the next method. Program Java0720.java, shown in Figure 7.27 demonstrates the finished program after the rest of the methods are implemented. Figure 7.27 // Java0720.java // Beginning a Big Graphics Program // Step 5 – Repeat step 4 until the entire program is done. import java.awt.*; import java.applet.*; public class Java0720 extends Applet { public void paint(Graphics g) { drawFloors(g); drawRoof(g); drawDoor(g); drawWindows(g); drawChimney(g); } Chapter VII Creating Class Methods 317 public static void drawFloors(Graphics g) { g.setColor(Color.blue); g.drawRect(200,200,300,100); g.drawRect(200,300,300,100); } public static void drawRoof(Graphics g) { g.setColor(Color.red); g.drawLine(200,200,350,100); g.drawLine(500,200,350,100); g.drawLine(200,200,500,200); } public static void drawDoor(Graphics g) { g.setColor(Color.black); g.drawRect(330,340,40,60); g.drawOval(340,350,20,40); g.fillOval(364,370,5,5); } public static void drawWindows(Graphics g) { g.setColor(Color.black); g.drawRect(220,220,60,60); g.drawLine(220,250,280,250); g.drawLine(250,220,250,280); g.drawRect(420,220,60,60); g.drawLine(420,250,480,250); g.drawLine(450,220,450,280); g.drawRect(320,220,60,60); g.drawLine(320,250,380,250); g.drawLine(350,220,350,280); g.drawRect(220,320,60,60); g.drawLine(220,350,280,350); g.drawLine(250,320,250,380); g.drawRect(420,320,60,60); g.drawLine(420,350,480,350); g.drawLine(450,320,450,380); } public static void drawChimney(Graphics g) { g.setColor(Color.red); g.drawLine(420,146,420,80); g.drawLine(420,80,450,80); g.drawLine(450,80,450,166); } } 318 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.27 Continued 7.6 Void Methods with a Single Parameter You have seen many program statements that call a wide variety of different methods. The majority of those methods use parameters or arguments to perform a desired computation. You do know that some methods do not require parameters, but most methods require some type of information for processing. In some cases, methods are overloaded. This means they can be used in different situations with different types of parameters or a different number of parameters. Chapter VII Creating Class Methods 319 Methods Calls With and Without Parameters Parameter method examples: double result1 = Math.sqrt(100); double result2 = Math.pow(2,5); g.drawLine(400,225,600,425); g.setColor(new Color(150,100,15)); Scanner input = new Scanner(System.in); Non-Parameter method examples: String name = input.nextLine(); int age = input.nextInt( ); double gpa = input.nextDouble(); Address.fullName( ); Address.street( ); Address.cityStateZip( ); Overloaded method examples: System.out.println(“Hello World”); System.out.println( ); Why is it that so many methods require parameters? This is very natural because methods perform some type of task. In most cases the task requires the processing of some type of information. A parameter passes this information to a method. If you look back at the past several graphics programs you will see that they also required the use of parameters – specifically the Graphics object g. This parameter needed to be passed to all methods that generated graphics output. 320 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Program Java0721.java, in Figure 7.28, is a small program with a small parameter method. When the displayParameter method is called, the parameter value of 100 is passed to the method, which displays this value. This is probably not very practical, but it does show how to call a method with a parameter. It also shows the method heading where the parameter is declared. The key difference between creating parameter methods and non-parameter methods is the parameter declaration. All method declarations have an identifier followed by parentheses. If no information is required for the method, the parentheses stay empty. If information is required then the method heading lists one or more parameters inside the parentheses. Make sure that you include the data type of each parameter. Figure 7.28 // Java0721.java // This program sends a value to a parameter method and then // displays the value of the parameter. public class Java0721 { public static void main(String args[]) { displayParameter(100); } public static void displayParameter(int number) { System.out.println("The parameter value is " + number); } } The parameter value is 100 Before moving on we need to get used to some parameter vocabulary. There are two kinds of parameters, which work together to pass information to a method. The calling parameter is officially called the actual parameter and the receiving parameter in the method heading is officially called the formal parameter. A copy of the information is passed from the actual parameter to the formal parameter. Chapter VII Creating Class Methods 321 Actual Parameters and Formal Parameters The 2 places we find parameters are in the method call and the method heading: Method Call Example displayParameter(100); Method Heading Example public static void displayParameter (int number) { Parameters in the method call are called actual parameters. Example: 100 Parameters in the method heading are called formal parameters. Example: number The Football Analogy In American football, the quarterback passes the ball to the receiver. When working with parameters the same thing essentially happens. The actual parameter is the quarterback. The formal parameter is the receiver. The data that is being passed from the actual parameter to the formal parameter is the football. 322 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 The formal parameters (the ones in the method heading) indicate the data types that must be passed by the actual parameters (the ones in the method call). The previous program example used a constant integer to pass the information. There are many ways to pass information and program Java0722.java, in Figure 7.29, shows that the actual parameter can take five different formats. It is possible to use a constant only, a variable only, an expression with constants only, an expression with a variable and a constant and a method call that returns the appropriate value. Figure 7.29 // Java0722.java // This program demonstrates that the calling parameter can be: // a constant, like 13 or Math.PI, a variable, like x, // an expression with constants and/or variables, like 20 + 30 and x + 5, // and a call to a method, which returns a value, like Math.sqrt(100). public class Java0722 { public static void main(String args[]) { double x = 100.0; displayParameter(13); displayParameter(x); displayParameter(20 + 30); displayParameter(x + 5); displayParameter(Math.PI); displayParameter(Math.sqrt(225)); } public static void displayParameter(double number) { System.out.println("The parameter value is " + number); System.out.println(); } } The parameter value is 13.0 The parameter value is 100.0 The parameter value is 50.0 The parameter value is 105.0 The parameter value is 3.141592653589793 The parameter value is 15.0 Chapter VII Creating Class Methods 323 Actual Parameters Formats Actual parameters can be constants (13) or (Math.PI) variables (x) expressions with constants only (20 + 30) expressions with variables & constants (x + 5) return method calls (Math.sqrt(225)) 7.7 Void Methods with Multiple Parameters You just saw that calling parameters can take on many different formats, but what about quantity? Are methods limited to a single parameter? Now you are new to creating your own methods, but you have used many method calls like g.drawLine(x1,y1,x2,y2); The drawLine method has four parameters. Using more than one parameter is certainly common in Java and it is not very difficult, but there are special considerations. Program Java0723.java, in Figure 7.30, uses a method that computes and displays the area of a rectangle. Note that the showArea method is called twice with the same value, but the second time the order of the calling parameters is reversed. The output is identical and may give the impression that parameter sequence is not an issue. The program is misleading; it is not an issue in this particular example, but as you will see, parameter sequence is very important. 324 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.30 // Java0723.java // This program demonstrates passing two parameters to a method. // The <showArea> method is called twice. In this case reversing // the sequence of the parameters is not a problem. public class Java0723 { public static void main(String args[]) { int length = 100; int width = 50; showArea(length, width); showArea(width, length); } public static void showArea(int L, int W) { int area = L * W; System.out.println("The rectangle area is " + area); System.out.println(); } } The rectangle area is 5000 The rectangle area is 5000 The reason program Java0723.java has no problem with sequence is due to the fact that the method operation is multiplication. You should know from Algebra that P x Q equals Q x P. Mathematical operations do not all have the same properties. How about subtraction? Can you say that P – Q = Q – P? This very question is answered by program Java0724.java, in Figure 7.31. Once again there is a user-defined method that displays the result of a mathematical operation, but this time it computes the difference. Method showDifference computes a - b and in this case the sequence of the calling parameters is very significant. The two outputs are now very different. Chapter VII Creating Class Methods 325 Figure 7.31 // Java0724.java // This program demonstrates that parameter sequence matters. // In this example method <showDifference> will display different // results when the calling parameters are reversed. public class Java0724 { public static void main(String args[]) { int num1 = 100; int num2 = 50; showDifference(num1,num2); showDifference(num2,num1); } public static void showDifference(int a, int b ) { int difference = a – b; System.out.println("The difference is " + difference); System.out.println(); } } The difference is 50 The difference is -50 Actual Parameter Sequence Matters The first actual parameter passes information to the first formal parameter. The second actual parameter passes information to the second formal parameter. Parameters placed out of sequence may result in compile errors or logic errors. 326 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Parameters are tricky critters and students make a bunch of mistakes with parameters when they are first introduced. Program Java0725.java, in Figure 7.32, demonstrates two common errors. Both errors will result in compile errors. In line 1 two actual parameters, num1 and num2, have data types inside the parentheses of the method call. This will not work. In line 2 there are two formal parameters, which appear to be declared as int. This also does not compile. Each formal parameter requires its own data type. Figure 7.32 // Java0725.java // This program demonstrates 2 common mistakes made by students. // The "Line 1" error is caused by defining variables in the method call. // The "Line 2" error is caused by not giving the 2nd formal parameter a data type. public class Java0725 { public static void main(String args[]) { showDifference(int num1, int num2); // Line 1 public static void showDifference(int a, b) // Line 2 } { System.out.println(); int difference = a - b; System.out.println("The difference is " + difference); System.out.println(); } } Chapter VII Creating Class Methods 327 Common Parameter Mistakes Wrong Correct qwerty(int num1, int num2); int num1 = 100; int num2 = 200; qwerty(num1,num2); public static void qwerty(int a, b); public static void qwerty(int a, int b) You have seen several programs using methods with multiple parameters. In each case the multiple parameters were all the same data type. This is not a requirement. Program Java0726.java, in Figure 7.33, demonstrates a multi-type method using three different parameter data types. The program worked because the data type of each actual parameter matches its corresponding formal parameter. You will notice a second method call that is commented out. The same parameters are in the second call, but they are on the wrong order. If the comment symbols were removed, the program would try to pass an int to a String, a double to an int, and a String to a double. This simply would not compile. Figure 7.33 // Java0726.java // This program demonstrates that multiple parameters may be // different data types. Parameter sequence is very important. public class Java0726 { public static void main(String args[]) { multiTypeDemo("Hans",30,3.575); multiTypeDemo(30,3.575,"Hans"); // // 3 different data types in a method call // same parameters, but in the wrong order } public static void multiTypeDemo(String studentName, int studentAge, double studentGPA) { System.out.println("\nThis method has 3 parameters with three different types"); System.out.println("Name: " + studentName); System.out.println("Age: " + studentAge); System.out.println("GPA: " + studentGPA); } } 328 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Output with the comment in place… This method has 3 parameters with three different types Name: Hans Age: 30 GPA: 3.575 Output with the comment removed… You can expect to use parameters in all your future programs. We have helped hundreds of students in Pascal, C++ and Java with their program writing problems. Mistakes that arise from incorrect parameter use certainly are at the top of the list for programs that do not compile. This section will finish with a track analogy. Look at the diagrams carefully and you will find that they illustrate the correct way to use parameters. Parameters will simplify your life. Your programs will be better designed. Your programs will be much shorter by using the same method for multiple situations. At the same time, your programs can give you headaches if parameters are not used correctly. Remember that actual parameters and formal parameters must match in 3 different ways: quantity, type and sequence. The Track Relay Analogy Let us summarize this parameter business, with a real life analogy that may help some students. The analogies that follow explain some of the parameter rules in a totally different manner. Imagine that you are at a track meet and you are watching a relay race. In this relay race the starters run 100 meters and then pass a baton to the next runner in their team. In the first relay race example, the race official checks the track and announces that the race is not ready. A look at Race-1 shows there are four starters ready in their lanes, but only three runners at the 100 meter baton passing mark. A runner Chapter VII Creating Class Methods 329 from the Netherlands (NL) is missing. If the four starting runners represent actual parameters and the three runners at the 100 meter mark represent formal parameters we have a situation where the quantity of actual parameters do not match. Race-1 US GB FR NL US GB FR Race-2 presents another situation with a different problem. This time the number of runners is correct. There are four starters and there are also four runners at the 100 meter mark ready to receive a baton. However two runners at the 100 meter mark are standing in the wrong lanes. The track official announces that the race cannot start unless the runners change lanes and are ready to receive the batons from their own countrymen. This represents a situation where the sequence of actual parameters and formal parameters do not match. Race-2 US GB FR NL US GB NL FR Race3 is not a problem situation. This race demonstrates an analogy to help explain the naming of parameters. In Race3, runner John starts for the United States (US) and passes to Greg. George starts for Great Britain (GB) and passes to Thomas. Gerard starts for France (FR) and passes to Louis. Finally, Hans starts for the Netherlands and passes to another guy named Hans. Race-3 US (John) GB (George) FR (Gerald) NL (Hans) 330 US (Greg) GB (Thomas) FR (Louis) NL (Hans) Exposure Java 2014 for teaching AP®CS Edition 07-25-14 The point of this analogy is that the names do not matter. What matters is that there are the same number of runners at the passing mark as there are in the starting blocks. It also matters that everybody stays in their lanes and that the runners receiving batons are on the same team as the starters. Note: The batons are not passed based on the names of the runners. They are passed based on the lanes they run in. Important Rules About Using Methods With Parameters #1 The number of parameters in the method call must match the number of parameters in the method heading. The corresponding parameters in the method call must be the same type as the parameters in the method heading. The sequence of the parameters in the method call must match the sequence of the parameters in the method heading. The identifiers of the parameters in the method call may be the same as or different from the identifiers of the parameters in the method heading. If you understand the definitions of actual parameters and formal parameters, it should make sense that the second set of rules below says the exact same thing as the first set above. The second set is just a little less wordy. Important Rules About Using Methods With Parameters #2 The number of actual parameters must match the number of formal parameters. The corresponding actual parameters must be the same type as the formal parameters. The sequence of the actual parameters must match the sequence of the formal parameters. The identifiers of the actual parameters may be the same as or different from the identifiers of the formal parameters. Chapter VII Creating Class Methods 331 7.8 Return Methods with a Single Parameter Every user-defined method you have seen thus far in this chapter started with the Java keywords public static void followed by the method names. Methods with the word void in the method heading are called void methods. The naming might be logical, but what exactly does it mean. The meaning of void methods makes more sense when you look at return methods. Program Java0727.java, in Figure 7.34, shows the user-created method getNextNumber¸ which does not use the keyword void in the method heading. At the place where you normally see void there is now the data type int. You will also see that the last statement in the method body is a return statement. The last program statement in a return method must always be a return statement. So far this seems logical. Void method have void in their heading and return methods end with a return statement. The purpose of a return method is to return a value to the calling method statement. This value has a data type. The data type of the returning value is declared in the method heading. If the method does not return a value, the return data type is not applicable and becomes void. Figure 7.34 // Java0727.java // This program introduces a return method with one parameter. // Method <getNextNumber> returns the next integer value of its parameter. public class Java0727 { public static void main(String args[]) { for (int k = 1; k <= 10; k++) { int rnd = (int)(Math.random() * 90) + 10; // [10..99] System.out.println("Random number : " + rnd); System.out.println("Next number : " + getNextNumber(rnd)); } } public static int getNextNumber(int n) { n++; return n; } } 332 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.34 Continued Random number: Next number : Random number: Next number : Random number: Next number : Random number: Next number : Random number: Next number : Random number: Next number : Random number: Next number : Random number: Next number : Random number: Next number : Random number: Next number : 73 74 21 22 15 16 22 23 21 22 69 70 13 14 39 40 24 25 78 79 Program Java0728.java, in Figure 7.35, shows a practical example of a return method. In this case the user-created method, checkPIN, returns the boolean value true or false depending upon the correct entry of a PIN (Personal Identification Number) that is needed to use a debit or credit card at an ATM (Automatic Teller Machine). The parameter value passed is the PIN number. This number is compared to 1234 and if the number matches, true is returned and false otherwise. This method is also a good example of the using the boolean data type. The boolean type only has two values, but these two values can be very practical. Figure 7.35 // Java0728.java // This example returns a <boolean> value, which is used // frequently to check for correct user keyboard input. import java.util.Scanner; public class Java0728 { public static void main(String args[]) { Scanner input = new Scanner(System.in); boolean okPIN = false; Chapter VII Creating Class Methods 333 do { System.out.print("Enter your four-digit PIN ===>> "); int pin = input.nextInt(); okPIN = checkPIN(pin); System.out.println(); } while (!okPIN); System.out.println("Select your bank transaction:"); } public static boolean checkPIN(int pin) { boolean temp = (pin == 1234); return temp; } } Figure 7.35 Continued Enter your four-digit PIN ===>> 4600 Enter your four-digit PIN ===>> 6623 Enter your four-digit PIN ===>> 1234 Select your bank transaction: 7.9 Return Methods with Multiple Parameters Return methods, like void methods can have multiple parameters. Program Java0729.java, in Figure 7.36, serves double duty. First, the program shows an example of a return method with two parameters. The method takes two parameters and returns the sum of the parameter values. Second, the program compares the similarities and differences of void methods with return methods by using both types of methods in the same program. 334 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.36 // Java0729.java // This program demonstrates the difference between a // void <add1> method and a return <add2> method. // There are two differences: // Void and return methods are declared differently. // Void and return methods are also called differently. public class Java0729 { public static void main(String args[]) { int nbr1 = 1000; int nbr2 = 100; add1(nbr1,nbr2); System.out.println(nbr1 + " + " + nbr2 + " = " + add2(nbr1,nbr2)); System.out.println(); } public static void add1(int n1, int n2) { int sum = n1 + n2; System.out.println(n1 + " + " + n2 + " = " + sum); } public static int add2(int n1, int n2) { int sum = n1 + n2; return sum; } } 1000 + 100 = 1100 1000 + 100 = 1100 Chapter VII Creating Class Methods 335 Void Methods and Return Methods Void Method Example public static void add1(int n1, int n2) { int sum = n1 + n2; System.out.println(n1 + " + " + n2 + " = " + sum); } Void methods do not return a value and use the void keyword in the method heading. Return Method Example public static int add2(int n1, int n2) { int sum = n1 + n2; return sum; } Return methods do return a value. The data type of the returned value is declared in the method heading. Additionally, the last statement in a return method must be a return statement. Program Java0730.java, in Figure 7.37, shows a four-function calculator. There are four user-defined return methods for add¸ subtract, multiply and divide operations. Each method is very similar and uses the same two parameters for a binary operation. It is very important to understand that return methods are called in a program statement that uses the return value. Void method calls stand by themselves. 336 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.37 // Java0730.java // This program demonstrates how to create a four-function <Calculator> class with return methods. public class Java0730 { public static void main(String args[]) { int nbr1 = 1000; int nbr2 = 100; System.out.println(nbr1 + " + " + nbr2 + " = " + Calculator.add(nbr1,nbr2)); System.out.println(nbr1 + " - " + nbr2 + " = " + Calculator.subtract(nbr1,nbr2)); System.out.println(nbr1 + " * " + nbr2 + " = " + Calculator.multiply(nbr1,nbr2)); System.out.println(nbr1 + " / " + nbr2 + " = " + Calculator.divide(nbr1,nbr2)); } } class Calculator { public static int add(int n1, int n2) { return n1 + n2; } public static int subtract(int n1, int n2) { return n1 - n2; } public static int multiply(int n1, int n2) { return n1 * n2; } public static int divide(int n1, int n2) { return n1 / n2; } } 1000 1000 1000 1000 + * / 100 100 100 100 = = = = 1100 900 100000 10 Chapter VII Creating Class Methods 337 We have seen that void methods and return methods are called differently. Void method calls are like a complete sentence. They can exist on their own. Return methods are like a subordinate clause. They are incomplete and need to be part of something else. This is because a return method returns a value and you need to do something with it. You can print it, or store it or compare it to another value. This is all demonstrated in program Java0731.java, shown in Figure 7.38. In this case add is called with an output display using println, with an assignment statement and finally with a boolean condition in a selection statement. In each example you will note the value returned by the add method is used in the program statement. Figure 7.38 // Java0731.java // This program reviews different ways to call a return method. public class Java0731 { public static void main(String args[]) { System.out.println("Sum: " + add(200,300)); int sum = add(400,500); System.out.println("Sum: " + sum); int checking = 600; int savings = 700; if (add(checking,savings) <= 0) System.out.println("You are broke!"); else System.out.println("Let's go shopping!"); } public static int add(int n1, int n2) { int sum = n1 + n2; return sum; } } Sum: 500 Sum: 900 Let's go shopping! 338 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 7.10 Introduction to Program Design You are about to study seven stages of a case study. Case studies help to explain computer science concepts by presenting a sequence of programs. Nobody writes a complete program in one simple step. Furthermore, many programmers make mistakes along the way of creating a complete and reliable program. A case study can also be an excellent tool in program development. Stages in the case study may intentionally be quite wrong, but they reflect a natural development process. In other words, it is hardly sufficient to teach computer science by simply showing a few Java keywords with some program examples to use the keywords. You also need to learn how to develop your own programs. The case study that follows will demonstrate the development of a payroll program. It is the intention of the case study to present the first set of information on program design. Program design is not an easy topic to teach or learn. There is quite a subjective side to program design. The Java compiler cares little about program design. On the other hand if you need to enhance your program six months later, you will greatly appreciate if you followed some fundamental rules of design. Likewise if you leave the job and somebody else takes over from a program that you started, the new programmer will appreciate if your program is developed in a manner that makes debugging and enhancement manageable. Program design does have some chicken and egg problems. The computer science community is concerned that students learn computer science and will form bad programming habits if design is not taught immediately. At the same time program design, makes little sense unless you have some fundamental knowledge of computer science. Not everybody agrees on the best approach to this design dilemma. At this stage you have now learned a sufficient amount of computer science to start investigating issues. The program design treatment in this chapter is not complete; it is a start. As you learn additional computer science concepts, the design concern will return at regular intervals. Payroll Case Study, Stage #1 Stage #1 is a very bad example of program design. I have never seen a student or anybody else program in this manner. The only reason why this stage is presented is to make a point. Students frequently complain about the need to use proper indentations or proper comments. Look at program Jav0732.java, in Figure 7.39. This program actually compiles and executes correctly. All the Chapter VII Creating Class Methods 339 source code runs together, there are no meaningful identifiers and no comments. This type of program is impossible to debug or enhance if it were a large program. Figure 7.39 // Java0732.java // Payroll Case Study #1 // The first stage of the Payroll program has correct syntax and logic. // However, there is no concern about any type of proper program design, // even to the degree that there is no program indentation. // This program is totally unreadable. import java.text.*;import java.util.Scanner;public class Java0732{ public static void main (String args[]){String a;double b,c,e,f,g,h,i,j,k;int d;DecimalFormat m=new DecimalFormat("$0.00");Scanner n = new Scanner(System.in); System.out.println( "\nPAYROLL CASE STUDY #1\n");System.out.print("Enter Name ===>> "); a = n.nextLine();System.out.print("Enter Hours Worked ===>> "); b = n.nextDouble(); System.out.print("Enter Hourly Rate ===>> ");c = n.nextDouble();System.out.print( System.out.print("Enter Dependents ===>> ");d = n.nextInt(); if (b > 40) { e = b - 40; k = 40 * c; j = e * c *1.5;} else{k=b*c;j=0;}g=k+j;switch (d) {case 0:f=29.5;break;case 1:f=24.9;break;case 2:f=18.7;break;case 3:f=15.5;break;case 4:f=12.6;break;case 5:f=10.0;break;default:f= 7.5;}i=g*f/100;h=g-i;System.out.println("\n"); System.out.println("Name: " + a); System.out.println("Hourly rate: "+ m.format(c)); System.out.println( "Hours worked: " +b);System.out.println("Dependents: " + d); System.out.println("Tax rate: " + f + "%"); System.out.println("Regular pay: " + m.format(k));System.out.println("Overtime pay: " + m.format(j));System.out.println( "Gross pay: "+m.format(g));System.out.println( "Deductions: "+m.format(i));System.out.println("Net pay: "+m.format(h));System.out.println("\n");}} PAYROLL CASE STUDY #1 Enter Enter Enter Enter Name Hours Worked Hourly Rate Dependents Name: Hourly rate: Hours worked: Dependents: Tax rate: Regular pay: Overtime pay: Gross pay: Deductions: Net pay: 340 ===>> ===>> ===>> ===>> Tom Jones 49 8.75 3 Tom Jones $8.75 49.0 3 15.5% $350.00 $118.12 $468.12 $72.56 $395.57 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Payroll Case Study, Stage #2 Program Java0733.java, in figure 7.40, makes a small improvement. Every program statement is written on a separate line. Block structure also uses indentation to indicate which statement will be executed. At the same time program statements within the same block are indented the same amount. This stage is a long way from a well-designed program. Variables like a, b, c, d, etc. may be fine in Algebra, but they make no sense in a computer program. Does a mean the gross pay or the net pay? Is b the number of hours worked or the number of dependents? The program output that follows is identical to the first stage. Future stages will not include program outputs. Figure 7.40 // Java0733.java // Payroll Case Study #2 // The second stage does use indentation, but it is still very poor program design. // All the program logic is contained in the <main> method and there are no program // comments anywhere, nor are the identifiers self-commenting. import java.text.*; import java.util.Scanner; public class Java0733 { public static void main (String args[]) { String a; double b,c,e,f,g,h,i,j,k; int d; DecimalFormat m = new DecimalFormat("$0.00"); Scanner n = new Scanner(System.in); System.out.println("\nPAYROLL CASE STUDY #2\n"); System.out.print("Enter Name ===>> "); a = n.nextLine(); System.out.print("Enter Hours Worked ===>> "); b = n.nextDouble(); System.out.print("Enter Hourly Rate ===>> "); c = n.nextDouble(); System.out.print("Enter Dependents ===>> "); d = n.nextInt(); if (b > 40) { e = b - 40; k = 40 * c; j = e * c * 1.5; } else { k = b * c; j = 0; } Chapter VII Creating Class Methods 341 g = k + j; switch (d) { case 0 : f = 29.5; break; case 1 : f = 24.9; break; case 2 : f = 18.7; break; case 3 : f = 15.5; break; case 4 : f = 12.6; break; case 5 : f = 10.0; break; default: f = 7.5; } i = g * f / 100; h = g - i; System.out.println("\n"); System.out.println("Name: System.out.println("Hourly rate: System.out.println("Hours worked: System.out.println("Dependents: System.out.println("Tax rate: System.out.println("Regular pay: System.out.println("Overtime pay: System.out.println("Gross pay: System.out.println("Deductions: System.out.println("Net pay: System.out.println("\n"); " + a); " + m.format(c)); " + b); " + d); " + f + "%"); " + m.format(k)); " + m.format(j)); " + m.format(g)); " + m.format(i)); " + m.format(h)); } } Figure 7.39 Continued PAYROLL CASE STUDY #2 Enter Enter Enter Enter Name Hours Worked Hourly Rate Dependents Name: Hourly rate: Hours worked: Dependents: Tax rate: Regular pay: Overtime pay: Gross pay: Deductions: Net pay: 342 ===>> ===>> ===>> ===>> Tom Jones 49 8.75 3 Tom Jones $8.75 49.0 3 15.5% $350.00 $118.12 $468.12 $72.56 $395.57 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Payroll Case Study, Stage #3 Stage #3 makes a large step forward to improving the program. The single-letter, meaningless identifiers of the previous stages, are now replaced with very readable self-commenting identifiers. Programs should have useful comments at strategic locations in the program, but the first step in commenting is to select good identifiers. With self-commenting identifiers, like Java0734.java, in Figure 7.41, you know anywhere in the program what the purpose of a variable should be. Identifiers like hoursWorked, grossPay and netPay provide an immediate clarification for the variable. Figure 7.41 // Java0734.java // Payroll Case Study #3 // Stage 3 improves program readability by using meaningful identifiers. import java.text.*; import java.util.Scanner; public class Java0734 { public static void main (String args[]) { String employeeName; double hoursWorked; double hourlyRate; int numDependents; double overtimeHours; double regularPay; double overtimePay; double taxRate; double grossPay; double taxDeductions; double netPay; DecimalFormat money = new DecimalFormat("$0.00"); Scanner input = new Scanner(System.in); System.out.println("\nPAYROLL CASE STUDY #3\n"); System.out.print("Enter Name ===>> "); employeeName = input.nextLine(); System.out.print("Enter Hours Worked ===>> "); hoursWorked = input.nextDouble(); System.out.print("Enter Hourly Rate ===>> "); hourlyRate = input.nextDouble(); System.out.print("Enter Dependents ===>> "); numDependents = input.nextInt(); if (hoursWorked > 40) { overtimeHours = hoursWorked - 40; regularPay = 40 * hourlyRate; Chapter VII Creating Class Methods 343 overtimePay = overtimeHours * hourlyRate * 1.5; } else { regularPay = hoursWorked * hourlyRate; overtimePay = 0; } grossPay = regularPay + overtimePay; switch (numDependents) { case 0 : taxRate = 29.5; break; case 1 : taxRate = 24.9; break; case 2 : taxRate = 18.7; break; case 3 : taxRate = 15.5; break; case 4 : taxRate = 12.6; break; case 5 : taxRate = 10.0; break; default: taxRate = 7.5; } taxDeductions = grossPay * taxRate / 100; netPay = grossPay - taxDeductions; System.out.println("\n"); System.out.println("Name: System.out.println("Hourly rate: System.out.println("Hours worked: System.out.println("Dependents: System.out.println("Tax rate: System.out.println("Regular pay: System.out.println("Overtime pay: System.out.println("Gross pay: System.out.println("Deductions: System.out.println("Net pay: System.out.println("\n"); " + employeeName); " + money.format(hourlyRate)); " + hoursWorked); " + numDependents); " + taxRate + "%"); " + money.format(regularPay)); " + money.format(overtimePay)); " + money.format(grossPay)); " + money.format(taxDeductions)); " + money.format(netPay)); } } Payroll Case Study, Stage #4 Program Java0735.java, in Figure 7.42, provides two improvements. Stage #4 adds comments and also separates the program into segments to help identify the purpose of a program segment. About ten years ago there was a student who made a beautiful horse for her graphics project. Everything looked great on the horse except for the tail. The tail was totally wrong and not attached anywhere on the horse. She asked for help and much to my surprise this student could not tell me the segment of her program responsible for drawing the tail. She had added program statement after program statement in one continuous, giant block of code. Debugging or enhancing such a program becomes a nightmare. 344 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.42 // Java0735.java // Payroll Case Study #4 // Stage 4 separates the program statements in the main method with spaces and comments // to help identify the purpose for each segment. This helps program debugging and updating. // Note that this program does not prevents erroneous input. import java.text.*; import java.util.Scanner; // used for text output with <DecimalFormat> class. // used for text/number input with the <Scanner> class. public class Java0735 { public static void main (String args[]) { ///////////////////////////////////////////////////////////////////////////////////////////// // Program variables // String employeeName; // employee name used on payroll check double hoursWorked; // hours worked per week double hourlyRate; // employee wage paid per hour int numDependents; // number of dependats declared for tax rate purposes double overtimeHours; // number of hours worked over 40 double regularPay; // pay earned for up to 40 hours worked double overtimePay; // pay earned for hours worked above 40 per week double taxRate; // tax rate, based on declared dependents, // used for deduction computation double grossPay; // total pay earned before deductions double taxDeductions; // total tax deductions double netPay; // total take-home pay, which is printed on the check ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // Program objects // DecimalFormat money = new DecimalFormat("$0.00"); // money is used to display values in monetary format. Scanner input = new Scanner(System.in); // input is used to enter the employee data. ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // Program input // System.out.println("\nPAYROLL CASE STUDY #4\n"); System.out.print("Enter Name ===>> "); employeeName = input.nextLine(); System.out.print("Enter Hours Worked ===>> "); hoursWorked = input.nextDouble(); System.out.print("Enter Hourly Rate ===>> "); hourlyRate = input.nextDouble(); System.out.print("Enter Dependents ===>> "); numDependents = input.nextInt(); ///////////////////////////////////////////////////////////////////////////////////////////// Chapter VII Creating Class Methods 345 ///////////////////////////////////////////////////////////////////////////////////////////// // Program computation // if (hoursWorked > 40) // qualifies for overtime pay { overtimeHours = hoursWorked - 40; regularPay = 40 * hourlyRate; overtimePay = overtimeHours * hourlyRate * 1.5; } else // does not qualify for overtime pay { regularPay = hoursWorked * hourlyRate; overtimePay = 0; } grossPay = regularPay + overtimePay; // compute total pay earned before any deductions switch (numDependents) { case 0 : taxRate = 29.5; break; case 1 : taxRate = 24.9; break; case 2 : taxRate = 18.7; break; case 3 : taxRate = 15.5; break; case 4 : taxRate = 12.6; break; case 5 : taxRate = 10.0; break; default: taxRate = 7.5; } taxDeductions = grossPay * taxRate / 100; // compute proper tax deductions based on the number of declared dependents netPay = grossPay - taxDeductions; // compute actual take-home-pay, which is printed on the paycheck ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// // Output display, which simulates the printing of a payroll check // System.out.println("\n"); System.out.println("Name: " + employeeName); System.out.println("Hourly rate: " + money.format(hourlyRate)); System.out.println("Hours worked: " + hoursWorked); System.out.println("Dependents: " + numDependents); System.out.println("Tax rate: " + taxRate + "%"); System.out.println("Regular pay: " + money.format(regularPay)); System.out.println("Overtime pay: " + money.format(overtimePay)); System.out.println("Gross pay: " + money.format(grossPay)); System.out.println("Deductions: " + money.format(taxDeductions)); System.out.println("Net pay: " + money.format(netPay)); System.out.println("\n"); ///////////////////////////////////////////////////////////////////////////////////////////// } } 346 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Payroll Case Study, Stage #5 The first four stages steadily improved from horrible, unreadable chaos, to a program that is readable and organized. Yet none of them satisfy the fundamental design principles of Object Oriented Programming. The main method of a program is not meant to contain detailed code. Program Java0736.java, in Figure 7.43, shows the 5th stage. You will observe that the program is divided up into five segments, each of which becomes a method. While the design and organization of the program is much improved there is one major issue. The program does not compile. The issue is not that we broke the program into different methods… at least not directly. The program has 49 compile errors because the variables are not dealt with properly. Right now we have all of the variables defined in the main method, which is what we have always done. Now that we have multiple methods we need to understand the difference between local variables and class variables. Local variables are defined inside a particular method. Only that method will have access to these variables. They simply do not exist outside of the method. Since all of our variables are defined inside the main method, they are local to the main method and do not exist anywhere else. Figure 7.43 // Java0736.java // Payroll Case Study #5 // Stage #5 is more in the spirit of modular programming. // The program is now divided into five separate methods, which // are called in sequence by the main method. // There is one major problem which causes many errors. // All of the variables are defined locally in the <main> method. // The other methods do not have access to them. import java.text.*; import java.util.Scanner; public class Java0736 { public static void main (String args[]) { String employeeName; double hoursWorked; double hourlyRate; int numDependents; double overtimeHours; double regularPay; double overtimePay; double taxRate; double grossPay; double taxDeductions; double netPay; DecimalFormat money = new DecimalFormat("$0.00"); Scanner input = new Scanner(System.in); Chapter VII Creating Class Methods 347 System.out.println("\nPAYROLL CASE STUDY #5\n"); enterData(); computeGrosspay(); computeDeductions(); computeNetpay(); printCheck(); } public static void enterData() { System.out.print("Enter Name ===>> "); employeeName = input.nextLine(); System.out.print("Enter Hours Worked ===>> "); hoursWorked = input.nextDouble(); System.out.print("Enter Hourly Rate ===>> "); hourlyRate = input.nextDouble(); System.out.print("Enter Dependents ===>> "); numDependents = input.nextInt(); } public static void computeGrosspay() { if (hoursWorked > 40) { overtimeHours = hoursWorked - 40; regularPay = 40 * hourlyRate; overtimePay = overtimeHours * hourlyRate * 1.5; } else { regularPay = hoursWorked * hourlyRate; overtimePay = 0; } grossPay = regularPay + overtimePay; } public static void computeDeductions() { switch (numDependents) { case 0 : taxRate = 29.5; break; case 1 : taxRate = 24.9; break; case 2 : taxRate = 18.7; break; case 3 : taxRate = 15.5; break; case 4 : taxRate = 12.6; break; case 5 : taxRate = 10.0; break; default: taxRate = 7.5; } taxDeductions = grossPay * taxRate / 100; } public static void computeNetpay() { netPay = grossPay - taxDeductions; } 348 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 public static void printCheck() { System.out.println("\n"); System.out.println("Name: System.out.println("Hourly rate: System.out.println("Hours worked: System.out.println("Dependents: System.out.println("Tax rate: System.out.println("Regular pay: System.out.println("Overtime pay: System.out.println("Gross pay: System.out.println("Deductions: System.out.println("Net pay: System.out.println("\n"); " + employeeName); " + money.format(hourlyRate)); " + hoursWorked); " + numDependents); " + taxRate + "%"); " + money.format(regularPay)); " + money.format(overtimePay)); " + money.format(grossPay)); " + money.format(taxDeductions)); " + money.format(netPay)); } } Figure 7.43 Continued : : : : Chapter VII Creating Class Methods 349 Payroll Case Study, Stage #6 To fix the problem from Stage 5, the variables have to be removed from the main method. Where do we put them? If we put them in any method, they will be local to that method and no other method will have access. The answer is not to put them in any method. Local variables are not appropriate in this situation. What we need are class variables. Class variables are not defined in any method, but they are defined within the class – usually at the top of the class before the first method. Class variables can be accessed by ALL methods of that class. Program Java0737.java, in Figure 7.44, used class variables and now it compiles. Figure 7.44 // Java0737.java // Payroll Case Study #6 // Stage #6 fixes the problem from Stage 5 by using class variables. // NOTE: The <input> and <money> objects are defined locally in the // <enterData> and <printCheck> methods respectively because // both objects are only accessed by their one respective method. import java.text.*; import java.util.Scanner; public class Java0737 { static String static double static double static int static double static double static double static double static double static double static double employeeName; hoursWorked; hourlyRate; numDependents; overtimeHours; regularPay; overtimePay; taxRate; grossPay; taxDeductions; netPay; public static void main (String args[]) { System.out.println("\nPAYROLL CASE STUDY #6\n"); enterData(); computeGrosspay(); computeDeductions(); computeNetpay(); printCheck(); } public static void enterData() { Scanner input = new Scanner(System.in); System.out.print("Enter Name ===>> "); employeeName = input.nextLine(); System.out.print("Enter Hours Worked ===>> "); 350 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 hoursWorked = input.nextDouble(); System.out.print("Enter Hourly Rate ===>> "); hourlyRate = input.nextDouble(); System.out.print("Enter Dependents ===>> "); numDependents = input.nextInt(); } public static void computeGrosspay() { if (hoursWorked > 40) { overtimeHours = hoursWorked - 40; regularPay = 40 * hourlyRate; overtimePay = overtimeHours * hourlyRate * 1.5; } else { regularPay = hoursWorked * hourlyRate; overtimePay = 0; } grossPay = regularPay + overtimePay; } public static void computeDeductions() { switch (numDependents) { case 0 : taxRate = 29.5; break; case 1 : taxRate = 24.9; break; case 2 : taxRate = 18.7; break; case 3 : taxRate = 15.5; break; case 4 : taxRate = 12.6; break; case 5 : taxRate = 10.0; break; default: taxRate = 7.5; } taxDeductions = grossPay * taxRate / 100; } public static void computeNetpay() { netPay = grossPay - taxDeductions; } public static void printCheck() { DecimalFormat money = new DecimalFormat("$0.00"); System.out.println("\n"); System.out.println("Name: " + employeeName); System.out.println("Hourly rate: " + money.format(hourlyRate)); System.out.println("Hours worked " + hoursWorked); System.out.println("Dependents: " + numDependents); System.out.println("Tax rate: " + taxRate + "%"); System.out.println("Regular pay: " + money.format(regularPay)); System.out.println("Overtime pay: " + money.format(overtimePay)); System.out.println("Gross pay: " + money.format(grossPay)); System.out.println("Deductions: " + money.format(taxDeductions)); System.out.println("Net pay: " + money.format(netPay)); System.out.println("\n"); } } Chapter VII Creating Class Methods 351 If you look closely, you will notice that not every variable in this class is a class variable. The input and money objects are defined as local variables in methods enterData and printCheck respectively. This is also part of proper program design. The input object is only used by method enterData, therefore it is defined locally inside enterData. The money object is only used by method printCheck, therefore it is defined locally inside printCheck. The other variables are all used in multiple methods; therefore they are defined as class variables. Payroll Case Study, Stage #7 In the second-to-last stage of this case study you will see a small, but important change. The driving class of a program, the one that contains the main method or the paint method, should not be stuffed full of methods. You have seen earlier that it is desirable to create a toolkit, called a class, filled with common tools, called methods. With that idea in mind the final stage presents a Payroll class, which contains all the methods involved with the payroll processing. Program Java0738.java, in Figure 7.45, shows that the Java0738 class now only contains the main which runs or drives the program by making several calls to methods of the Payroll class. NOTE: Another word for a Class Variable is an attribute. netPay is an attribute of the Payroll class just like PI is an attribute of the Math class. Figure 7.45 // Java0738.java // Payroll Case Study #7 // In Stage #7 the <main> method is part of the "driving" class, which is the class // responsible for the program execution sequence. The <main> method now contains // method calls to objects of the <Payroll> class. import java.text.*; import java.util.Scanner; public class Java0738 { public static void main (String args[]) { System.out.println("\nPAYROLL CASE STUDY #7\n"); Payroll.enterData(); Payroll.computeGrosspay(); Payroll.computeDeductions(); Payroll.computeNetpay(); Payroll.printCheck(); } } class Payroll { static String static double 352 employeeName; hoursWorked; Exposure Java 2014 for teaching AP®CS Edition 07-25-14 static double static int static double static double static double static double static double static double static double hourlyRate; numDependents; overtimeHours; regularPay; overtimePay; taxRate; grossPay; taxDeductions; netPay; public static void enterData() { Scanner input = new Scanner(System.in); System.out.print("Enter Name ===>> "); employeeName = input.nextLine(); System.out.print("Enter Hours Worked ===>> "); hoursWorked = input.nextDouble(); System.out.print("Enter Hourly Rate ===>> "); hourlyRate = input.nextDouble(); System.out.print("Enter Dependents ===>> "); numDependents = input.nextInt(); } public static void computeGrosspay() { if (hoursWorked > 40) { overtimeHours = hoursWorked - 40; regularPay = 40 * hourlyRate; overtimePay = overtimeHours * hourlyRate * 1.5; } else { regularPay = hoursWorked * hourlyRate; overtimePay = 0; } grossPay = regularPay + overtimePay; } public static void computeDeductions() { switch (numDependents) { case 0 : taxRate = 29.5; break; case 1 : taxRate = 24.9; break; case 2 : taxRate = 18.7; break; case 3 : taxRate = 15.5; break; case 4 : taxRate = 12.6; break; case 5 : taxRate = 10.0; break; default: taxRate = 7.5; } taxDeductions = grossPay * taxRate / 100; } public static void computeNetpay() { netPay = grossPay - taxDeductions; } public static void printCheck() { DecimalFormat money = new DecimalFormat("$0.00"); System.out.println("\n"); System.out.println("Name: " + employeeName); System.out.println("Hourly rate: " + money.format(hourlyRate)); System.out.println("Hours worked: " + hoursWorked); System.out.println("Dependents: " + numDependents); System.out.println("Tax rate: " + taxRate + "%"); System.out.println("Regular pay: " + money.format(regularPay)); System.out.println("Overtime pay: " + money.format(overtimePay)); System.out.println("Gross pay: " + money.format(grossPay)); System.out.println("Deductions: " + money.format(taxDeductions)); System.out.println("Net pay: " + money.format(netPay)); System.out.println("\n"); } } Chapter VII Creating Class Methods 353 Payroll Case Study, Stage #8 In the final stage of this case study the program is broken up into different files. This is in accordance with one of the principals of proper programming design which states that every class should be placed in its own file. Both files can be found in the Java0739 folder. Figure 7.46 shows program Java0739.java which contains the driving class for the program. Figure 7.47 shows the Payroll.java file which contains the Payroll class. This is in accordance with another rule which states that the name of the file must match the name of the public class. Figure 7.46 // Java0739.java // Payroll Case Study #8 // In Stage #8 the driving class and the <Payroll> class are each placed in separate files. public class Java0739 { public static void main (String args[]) { System.out.println("\nPAYROLL CASE STUDY #8\n"); Payroll.enterData(); Payroll.computeGrosspay(); Payroll.computeDeductions(); Payroll.computeNetpay(); Payroll.printCheck(); } } Figure 7.47 // Payroll.java import java.text.*; public class Payroll { static String static double static double static int static double static double static double static double static double static double static double employeeName; hoursWorked; hourlyRate; numDependents; overtimeHours; regularPay; overtimePay; taxRate; grossPay; taxDeductions; netPay; public static void enterData() { Scanner input = new Scanner(System.in); System.out.print("Enter Name ===>> "); employeeName = input.nextLine(); 354 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 System.out.print("Enter Hours Worked ===>> "); hoursWorked = input.nextDouble(); System.out.print("Enter Hourly Rate ===>> "); hourlyRate = input.nextDouble(); System.out.print("Enter Dependents ===>> "); numDependents = input.nextInt(); } public static void computeGrosspay() { if (hoursWorked > 40) { overtimeHours = hoursWorked - 40; regularPay = 40 * hourlyRate; overtimePay = overtimeHours * hourlyRate * 1.5; } else { regularPay = hoursWorked * hourlyRate; overtimePay = 0; } grossPay = regularPay + overtimePay; } public static void computeDeductions() { switch (numDependents) { case 0 : taxRate = 29.5; break; case 1 : taxRate = 24.9; break; case 2 : taxRate = 18.7; break; case 3 : taxRate = 15.5; break; case 4 : taxRate = 12.6; break; case 5 : taxRate = 10.0; break; default: taxRate = 7.5; } taxDeductions = grossPay * taxRate / 100; } public static void computeNetpay() { netPay = grossPay - taxDeductions; } public static void printCheck() { DecimalFormat money = new DecimalFormat("$0.00"); System.out.println("\n"); System.out.println("Name: " + employeeName); System.out.println("Hourly rate: " + money.format(hourlyRate)); System.out.println("Hours worked: " + hoursWorked); System.out.println("Dependents: " + numDependents); System.out.println("Tax rate: " + taxRate + "%"); System.out.println("Regular pay: " + money.format(regularPay)); System.out.println("Overtime pay: " + money.format(overtimePay)); System.out.println("Gross pay: " + money.format(grossPay)); System.out.println("Deductions: " + money.format(taxDeductions)); System.out.println("Net pay: " + money.format(netPay)); System.out.println("\n"); } } Chapter VII Creating Class Methods 355 Local Variables and Class Variables Variables that are declared inside a method or block are called local variables. Local variables are only accessible inside the method or block that they are defined in. Variables that are declared inside a class, but outside any method, are class variables. Class variables are accessible by any method of the class. Class variables are also called attributes. If a variable is only used by one method, it should be declared inside that method as a local variable. If a variable is used by 2 or more methods of a class, it should be declared as a class variable. Program Design Notes This was the first introduction to program design. Additional design features will be introduced as you learn more ObjectOriented Programming. At this stage you can already consider the following: • Programs should use self-commenting identifiers. • Control structures and block structures need to use a consistent indentation style. • Specific tasks should be placed in modules called methods. • Similar methods accessing the same data should be placed in a class. • The main method should be used for program sequence, not large numbers of program statements. 356 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 7.11 Creating Methods with Other Methods The last section in this chapter will look at creating some user-defined methods and then using the newly created methods for more complex methods. The first program starts with a modest little method that displays a single brown picket. The picket method in Java0740.java, shown in Figure 7.48, has only two program statements. It is small, but the program will steadily grow to an interesting graphics display with many user-defined methods. Figure 7.48 // Java0740.java // This program demonstrates a <picket> method that will be used // to display a fence. import java.awt.*; import java.applet.*; public class Java0740 extends Applet { public void paint(Graphics g) { g.setColor(Color.black); g.fillRect(0,0,1000,650); // 2 Cross Beams g.setColor(new Color(210,180,140)); // tan g.fillRect(0,500,1000,25); g.fillRect(0,600,1000,25); // 25 Pickets g.setColor(new Color(150,100,15)); // brown for (int x = 2; x < 1000; x+=40) { picket(g,x); } } public static void picket(Graphics g, int x) { Polygon picket = new Polygon(); picket.addPoint(x,650); picket.addPoint(x,500); picket.addPoint(x+18,450); picket.addPoint(x+36,500); picket.addPoint(x+36,650); g.fillPolygon(picket); } } Chapter VII Creating Class Methods 357 Figure 7.48 Continued The next program example, Java0741.java, in Figure 7.49, displays the same picket fence. This time you will see an example of a user-defined method using another user-defined method. You will see a new fence method, which uses the previously created picket method. This follows the philosophy of not reinventing the wheel. Figure 7.49 // Java0741.java // This program uses the <picket> method to create the <fence> method. import java.awt.*; import java.applet.*; public class Java0741 extends Applet { public void paint(Graphics g) { g.setColor(Color.black); g.fillRect(0,0,1000,650); fence(g); } 358 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 public static void picket(Graphics g, int x) { Polygon picket = new Polygon(); picket.addPoint(x,650); picket.addPoint(x,500); picket.addPoint(x+18,450); picket.addPoint(x+36,500); picket.addPoint(x+36,650); g.fillPolygon(picket); } public static void fence(Graphics g) { // 2 Cross Beams g.setColor(new Color(210,180,140)); // tan g.fillRect(0,500,1000,25); g.fillRect(0,600,1000,25); // 25 Pickets g.setColor(new Color(150,100,15)); // brown for (int x = 2; x < 1000; x+=40) { picket(g,x); } } } 7.12 Making a Utility Library Class As you program more and more, you will notice that certain tasks seem to show up again and again in several programs. Some example would include getting a random number in a specified range and setting a color for the entire background or selecting a random color. Rather than write these methods again and again, you could create your own utility class and store several useful methods. Chapter VII Creating Class Methods 359 Figure 7.50 shows the file Utility.java. This file contains 3 methods: random, setBackground and setRandomColor. Look closely at the setRandomColor method. There are a couple things you should notice. First, this is another example of one method calling another. The setRandomColor method calls the random method (3 times actually). Second, when the random method is called, it is not done with Utility.random(0,255). Remember, the class name is not needed here because both methods are in the same class. Figure 7.50 // Utility.java // This file contains useful methods that can be used by several different programs. import java.awt.*; import java.applet.*; public class Utility { public static int random(int min, int max) { int range = max - min + 1; int randomNumber = (int)(Math.random() * range) + min; return randomNumber; } public static void setBackground(Graphics g, Color c) { g.setColor(c); g.fillRect(0,0,1000,650); } public static void setRandomColor(Graphics g) { int red = random(0,255); int green = random(0,255); int blue = random(0,255); g.setColor(new Color(red, green, blue)); } } While this is a very small file, it is something that can grow over time as your knowledge grows. NOTE: Utility libraries do NOT have to be named Utility. You can have several different utility classes with different name. 360 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 You may have noticed that the previous 2 programs started by making the entire applet black. The black background is intentional. We are looking at a picket fence at night. There are a couple things missing from our night sky, namely the moon and some stars. Program Java0742.java, in Figure 7.51, fixes this with a new nightSky method which starts by making the bakcground black and then calls both the moon and randomStar methods. As before, the fence method calls the picket method. You will note that methods of the Utility class are called as well in certain key locations. Figure 7.51 // Java0742.java // This program combines many user-defined methods to create a graphics image. // Some of the methods calls are for methods in the <Utility.java> file import java.awt.*; import java.applet.*; public class Java0742 extends Applet { public void paint(Graphics g) { nightSky(g); fence(g); } public static void randomStar(Graphics g) { int x = Utility.random(0,996); int y = Utility.random(0,296); Utility.setRandomColor(g); g.fillRect(x,y,3,3); } public static void nightSky(Graphics g) { Utility.setBackground(g,Color.black); // 100 random stars for (int j = 1; j <= 100; j++) { randomStar(g); } moon(g); } Chapter VII Creating Class Methods 361 public static void moon(Graphics g) { g.setColor(Color.white); g.fillOval(850,15,140,140); g.setColor(Color.black); g.fillOval(835,10,120,120); } public static void picket(Graphics g, int x) { Polygon picket = new Polygon(); picket.addPoint(x,650); picket.addPoint(x,500); picket.addPoint(x+18,450); picket.addPoint(x+36,500); picket.addPoint(x+36,650); g.fillPolygon(picket); } public static void fence(Graphics g) { // 2 Cross Beams g.setColor(new Color(210,180,140)); // tan g.fillRect(0,500,1000,25); g.fillRect(0,600,1000,25); // 25 Pickets g.setColor(new Color(150,100,15)); // brown for (int x = 2; x < 1000; x+=40) { picket(g,x); } } } 362 Exposure Java 2014 for teaching AP®CS Edition 07-25-14 Figure 7.51 Continued There is no end to this process. Java and other program languages allow a contiuous use of user-defined subroutines to organzie and simplify program writing. There also is a sense of reliability, because a class can be created by itself and placed in a program with a tester or runner class to make sure that the user-defined class and user-defined methods work correctly. A team of programmers can work together and each take responbility for creating tools that then turn around and become practical program library of subroutines that can create very complex programs. Video games are classic examples of specialized routines that are created to control game objects in many different situations. If you consider that modern sophisticated video games are frequerntly more than 500,000 lines of program code, you can then realize the need for program organization and efficiency. Chapter VII Creating Class Methods 363 7.13 Summary This chapter focused on writing class methods. Methods can be members in classes and they can also be members inside an object. The distinction between creating class methods and object methods will be cleared up when creating object methods is demonstrated in the next chapter. Class methods are called by using the class identifier followed by a period and the method identifier. This is called class-dot-method notation. This type of syntax is necessary because the class contains multiple members. It requires two identifiers to first identify the class and then identify the method within the class. A popular, Java-provided class is the Math class. This class provides a variety of useful math functions, such as square root, absolute value, truncate, logarithmic and trigonometric functions. Java allows programmers to declare their own classes and methods. It is possible to add methods to the existing main class of the program. It is also possible to declare a second class or multiple classes outside the main class. And even place them in other files. If a statement calls a member method of the same class, the class identifier is optional. Anytime that a method is called from a class declared outside the calling statement’s class, the class identifier must be provided. Methods can be declared with or without parameters. In either case a set of parentheses follows the method identifier. In the method declaration parameters need to be declared in the same manner as any other variable declaration, except that each parameter must have its own data type. The parameters in the method call must match the parameters in the method declaration in quantity, type and sequence. Parameters in a method call can be literal constants, variables or expressions. This chapter introduced the important concept of program design. Program design was demonstrated by using a case study that started with a very poorly written program and improved with small incremental stages. Finally it was shown that once a method is created, it can be used to create other methods as well and frequently used methods can also be placed in special utility classes. 364 Exposure Java 2014 for teaching AP®CS Edition 07-25-14