Now that you have been introduced to the Java class construct in more detail it’s time to apply some of what was discussed above to create and test the Person class. To get the Person class in working order you will have to take the results of the analysis performed earlier and map attributes and functionality to fields and methods. As you build the Person class you may discover that you need to add more fields or methods to fully implement the class to your satisfaction. That’s a normal part of the programming process.
To write the code for the Person class I will use the development cycle presented in chapter 1 and explained in detail in chapter 3. The development cycle is applied iteratively. (i.e., I will apply the steps of plan, code, test, and integrate repeatedly until I have completed the code.)
I recommend you start this process by creating the Person.java source file and the Person class definition shell. Example 9.1 gives the code for this early stage of the program.
Example 9.1: Person.java (1st Iteration)
![]() |
3 public class Person { 4 5 } //end Person class
![]() |
At this point I recommend you compile the code to ensure you’ve typed everything correctly and that the name of the class matches the name of the file. The next thing to do would be to refer to table 9-1 and see what attributes or fields the Person class must contain and add those fields. This is done in the next section.
Referring to table 9-1 you learn that the Person class represents a person entity in our problem domain. Each person has their own name, gender, and birthdate so these are good candidates for instance fields in the Person class. Example 9.2 shows the Person class code after the instance fields have been added.
Example 9.2: Person.java (2nd Iteration)
![]() |
1 import java.util.*; 2 3 public class Person { 4 private String first_name = null; 5 private String middle_name = null; 6 private String last_name = null; 7 private Calendar birthday = null; 8 private String gender= null; 9 10 } //end Person class
![]() |
Two Java API classes are used for the fields in example 9.2: String and Calendar. The import statement is used on line 1 to provide shortcut naming for the Calendar class. These fields represent a first attempt at defining fields for the Person class. Each field is declared to be private which means they will be encapsulated by the Person class to prevent horizontal access. The only way to access or modify these fields will be through the Person class’s public interface methods. Let’s define a few of those right now. But, before you move on, compile the Person.java source file again to make sure you didn’t break anything.
Now that several Person class instance fields have been defined it’s time to define a few methods. After you’ve defined several methods you can use them to test those aspects of Person class behavior. A good place to start is with the constructor method and several getter and setter methods. (i.e., methods whose names begin with get and set.)
A good method to define first is the constructor method. Remember, the purpose of the constructor method is to properly initialize an object when it is created in memory. In the case of the Person class this means that each person object’s fields must be initialized to some valid value. To make this happen I will add a constructor method that takes a parameter list that matches the fields contained in the Person class. These parameters will then be used to initialize each field. Example 9.3 gives the code for the Person class definition after the constructor has been added.
Example 9.3: Person.java (3rd Iteration)
![]() |
1 import java.util.*; 2 3 public class Person { 4 private String first_name = null; 5 private String middle_name = null; 6 private String last_name = null; 7 private String date_of_birth = null; 8 private Calendar birthday = null; 9 private String gender = null; 10 11 public Person(String f_name, String m_name, String l_name, 12 int dob_year, int dob_month, int dob_day, String gender){ 13 first_name = f_name; 14 middle_name = m_name; 15 last_name = l_name; 16 this.gender = gender; 17 18 birthday = Calendar.getInstance(); 19 birthday.set(dob_year, dob_month, dob_day); 20 } 21 22 } // end Person class
![]() |
The Person constructor method begins on line 11. Notice that it is declared to be public and has no return value. It has seven parameters. The first three parameters, f_name, m_name, and l_name are used on lines 13, 14, and 15 to initialize the instance fields first_name, middle_name, and last_name.
The next three constructor parameters: dob_year, dob_month, and dob_day are used to initialize a Person object’s birthday Calendar object. This is done on line 19 after the Calendar.getInstance() method call is used to initialize the birthday reference. (If you haven’t already studied the Calendar class functionality you might want to do so now.)
The last parameter, gender, is used on line 16 to initialize the instance field having the same name. Since the parameter name gender will hide the field named gender it is required to prefix the field name with the this keyword so the compiler can tell the difference between the field and the parameter. There are other ways you could handle this situation. For example, you could start each field name with an underscore ‘__’ character so that when you refer to a field in a method you and the compiler would know the difference between fields and local method variables. If you used this approach the field named gender would become _gender and the assignment on line 16 would then take the following form:
_gender = gender;
OK, now that you’ve got the constructor written compile the Person.java source file to ensure you didn’t break anything. It’s now time to add a few more methods so we can test this puppy.
Accessor methods are methods that simply return some sort of object state information. Accessor methods do not alter or modify the fields they access or do anything else that might change the state of the object. A good place to start would be to add a few accessor methods to return a Person object’s first name, middle name, last name, and gender. These methods will be easy to write. Once these methods are in place we can use the Person class in another program and test its functionality. Example 9.4 shows the Person class after these accessor methods have been added.
Example 9.4: Person.java (4th Iteration)
![]() |
1 import java.util.*; 2 3 public class Person { 4 private String first_name = null; 5 private String middle_name = null; 6 private String last_name = null; 7 private Calendar birthday = null; 8 private String gender = null; 9 10 public Person(String f_name, String m_name, String l_name, 11 int dob_year, int dob_month, int dob_day, String gender){ 12 first_name = f_name; 13 middle_name = m_name; 14 last_name = l_name; 15 this.gender = gender; 16 birthday = Calendar.getInstance(); 17 birthday.set(dob_year, dob_month, dob_day); 18 } 19 20 public String getFirstName(){ return first_name;} 21 22 public String getMiddleName(){ return middle_name;} 23 24 public String getLastName(){ return last_name; } 25 26 public String getGender(){ return gender;} 27 28 } //end Person class
![]() |
The accessor methods appear on lines 20, 22, 24, and 26. Each method returns a String object and each method name begins with the word get followed by the name of the particular property being retrieved. The convention of preceding accessor methods (also referred to as getters) with the word get followed by the property name beginning with a capital letter is not arbitrary. This convention conforms to the Java Beans specification. For now, I recommend you adopt the convention. Doing so will make the transition to professional Java programmer much easier.
With the constructor and getter methods in place compile the source code and get ready for testing.
Testing the Person class at this stage of the development cycle will consist of creating a Person object and calling each getter method. This will effectively test the constructor and accessor methods.
To test the Person class functionality you’ll need to create another class that’s a Java application. Since you need to create the PeopleManagerApplication class anyway you might as well use that class as a test driver. (The term driver means a small program written specifically to run or test another program.) Example 9.5 gives the code for the PeopleManagerApplication class with a few lines of code that tests the functionality of the Person class developed thus far. Figure 9-6 shows the results of running this program.
Example 9.5: PeopleManagerApplication.java (Testing Person)
![]() |
1 public class PeopleManagerApplication { 2 public static void main(String[] args){ 3 Person p1 = new Person("Steve", "Jason", "Brown", 1980, 3, 4, "Male"); 4 5 System.out.println(p1.getFirstName() + " " + p1.getMiddleName() 6 + " " + p1.getLastName() + " - " + p1.getGender()); 7 } // end main 8 } // end PeopleManagerApplication class
![]() |
Figure 9-6: Results of Running Example 9.5
Everything appears to run fine. It’s now time to add a few more features to the Person class.
Returning to table 9-1 for some direction reveals the requirement to calculate a person’s age. This could be done in several ways. Reflect for a moment on how you get the age of a real live person. You might ask them for their birth date and perform the calculation yourself. You would have to know today’s date and subtract their birth date to yield the answer. Another way would be to just ask the person how old they are. They would do the calculation for you and they would have to know today’s date to do that. For this example I am going to go with the last scenario. I will add an accessor method named getAge() that computes the person’s age and returns the result. Example 9.6 shows the modified Person class code.
Example 9.6: Person.java (5th Iteration)
![]() |
1 import java.util.*; 2 3 public class Person { 4 private String first_name = null; 5 private String middle_name = null; 6 private String last_name = null; 7 private Calendar birthday = null; 8 private String gender = null; 9 10 public static final String MALE = "Male"; 11 public static final String FEMALE = "Female"; 12 13 public Person(String f_name, String m_name, String l_name, int dob_year, 14 int dob_month, int dob_day, String gender){ 15 first_name = f_name; 16 middle_name = m_name; 17 last_name = l_name; 18 this.gender = gender; 19 20 birthday = Calendar.getInstance(); 21 birthday.set(dob_year, dob_month, dob_day); 22 } 23 24 /************** Added the getAge() method ****************/ 25 public int getAge(){ 26 Calendar today = Calendar.getInstance(); 27 int now = today.get(Calendar.YEAR); 28 int then = birthday.get(Calendar.YEAR); 29 return (now - then); 30 } 31 32 public String getFirstName(){ return first_name; } 33 34 public String getMiddleName(){ return middle_name; } 35 36 public String getLastName(){ return last_name; } 37 38 public String getGender(){ return gender; } 39 40 } //end Person class
![]() |
After making the necessary modifications to the Person class you can test the changes in the PeopleManagerApplication class. Example 9.7 shows the code for the modified PeopleManagerApplication class. Figure 9-7 shows the results of running this program.
Example 9.7: PeopleManagerApplication.java (Testing Person age functionality)
![]() |
1 public class PeopleManagerApplication { 2 public static void main(String[] args){ 3 Person p1 = new Person("Steve", "Jason", "Brown", 1980, 3, 4, "Male"); 4 5 System.out.println(p1.getFirstName() + " " + p1.getMiddleName() 6 + " " + p1.getLastName() + " - " + p1.getGender()); 7 System.out.println(p1.getFirstName() + " is " + p1.getAge() + " years old!"); 8 9 } // end main 10 }// end PeopleManagerApplication class
![]() |
Figure 9-7: Results of Running Example 9.7
The age feature seems to work pretty good. However, from looking at the code in example 9.7 it sure looks like a hassle to get a Person object’s full name. It might be a good idea to add an accessor method that will do the job for you. While you’re at it you could add a method that returns both the full name and age. Example 9.8 shows the modified Person class.
Example 9.8: Person.java (6th Iteration)
![]() |
1 import java.util.*; 2 3 public class Person { 4 private String first_name = null; 5 private String middle_name = null; 6 private String last_name = null; 7 private Calendar birthday = null; 8 private String gender = null; 9 10 public static final String MALE = "Male"; 11 public static final String FEMALE = "Female"; 12 13 public Person(String f_name, String m_name, String l_name, int dob_year, 14 int dob_month, int dob_day, String gender){ 15 first_name = f_name; 16 middle_name = m_name; 17 last_name = l_name; 18 this.gender = gender; 19 20 birthday = Calendar.getInstance(); 21 birthday.set(dob_year, dob_month, dob_day); 22 } 23 24 public int getAge(){ 25 Calendar today = Calendar.getInstance(); 26 int now = today.get(Calendar.YEAR); 27 int then = birthday.get(Calendar.YEAR); 28 return (now - then); 29 } 30 31 public String getFullName(){ return (first_name + " " + middle_name + " " + last_name); } 32 33 public String getFirstName(){ return first_name; } 34 35 public String getMiddleName(){ return middle_name; } 36 37 public String getLastName(){ return last_name; } 38 39 public String getNameAndAge(){ return (getFullName() + " " + getAge()); } 40 41 public String getGender(){ return gender; } 42 43 } //end Person class
![]() |
Referring to example 9.8 — the getFullName() method appears on line 31. It simply concatenates the fields first_name, middle_name, and last_name with spaces and returns the resulting String object that represents the Person object’s full name.
The getNameAndAge() method on line 39 utilizes the services of the getFullName() and getAge() methods. This is a good example of code reuse at the class level. Since the methods exist and already provide the required functionality it’s a good idea to use them.
It’s time to compile the Person class and test the changes. Example 9.9 gives the modified PeopleManagerApplication class with the changes required to test the Person class’s new functionality. Notice the code is a lot cleaner now. Figure 9-8 shows the results of running this program.
Example 9.9: PeopleManagerApplication.java (Testing new Person functionality)
![]() |
1 public class PeopleManagerApplication { 2 public static void main(String[] args){ 3 Person p1 = new Person("Steve", "Jason", "Brown", 1980, 3, 4, "Male"); 4 5 System.out.println(p1.getFullName() + " - " + p1.getGender()); 6 System.out.println(p1.getFirstName() + " is " + p1.getAge() + " years old!"); 7 System.out.println("Testing getNameAndAge() method: " + p1.getNameAndAge()); 8 9 } // end main 10 }// end PeopleManagerApplication class
![]() |
Figure 9-8: Results of Running Example 9.9
It looks like the Person class is beginning to take shape. Referring to table 9-1 for some final advice reveals that you must be able to set each of the Person attributes as well as query them. This is accomplished by adding mutator or setter methods. Setter methods begin with the word set followed by the property name they are setting. If you are building the capability into a class to get and set a property then the property name used in the getter method will match the property name in the corresponding setter method.
In addition to the setter methods I will add a set of Person class-wide constants to represent the genders Male and Female. These will be String constants that can be used in the Person constructor call to supply the correctly formed string to the gender field.
The getter method getAge() will not have a corresponding setter method. (i.e., I will not write a setAge() method.) I will instead write a setBirthday() method that will set the year, month, and day of a Person object’s birthday Calendar object. Then, when the getAge() method is next called it will calculate the new age.
Example 9.10 gives the modified Person class source code.
Example 9.10: Person.java (Final Iteration)
![]() |
1 import java.util.*; 2 3 public class Person { 4 private String first_name = null; 5 private String middle_name = null; 6 private String last_name = null; 7 private Calendar birthday = null; 8 private String gender = null; 9 10 public static final String MALE = "Male"; 11 public static final String FEMALE = "Female"; 12 13 public Person(String f_name, String m_name, String l_name, int dob_year, 14 int dob_month, int dob_day, String gender){ 15 first_name = f_name; 16 middle_name = m_name; 17 last_name = l_name; 18 this.gender = gender; 19 20 birthday = Calendar.getInstance(); 21 birthday.set(dob_year, dob_month, dob_day); 22 } 23 24 public int getAge(){ 25 Calendar today = Calendar.getInstance(); 26 int now = today.get(Calendar.YEAR); 27 int then = birthday.get(Calendar.YEAR); 28 return (now - then); 29 } 30 31 public String getFullName(){ return (first_name + " " + middle_name + " " + last_name); } 32 33 public String getFirstName(){ return first_name; } 34 public void setFirstName(String f_name) { first_name = f_name; } 35 36 public String getMiddleName(){ return middle_name; } 37 public void setMiddleName(String m_name){ middle_name = m_name; } 38 39 public String getLastName(){ return last_name; } 40 public void setLastName(String l_name){ last_name = l_name; } 41 42 public String getNameAndAge(){ return (getFullName() + " " + getAge()); } 43 44 public String getGender(){ return gender; } 45 public void setGender(String gender){ this.gender = gender; } 46 47 public void setBirthday(int year, int month, int day){ birthday.set(year, month, day); } 48 49 } //end Person class
![]() |
Example 9.11 shows the new Person class functionality being tested in the PeopleManagerApplication class. Figure 9-9 shows the results of running this program.
Example 9.11: PeopleManagerApplication.java (Final Person test)
![]() |
1 public class PeopleManagerApplication { 2 public static void main(String[] args){ 3 Person p1 = new Person("Steve", "Jason", "Brown", 1980, 3, 4, Person.MALE); 4 5 System.out.println(p1.getFullName() + " - " + p1.getGender()); 6 System.out.println(p1.getFirstName() + " is " + p1.getAge() + " years old!"); 7 System.out.println("Testing getNameAndAge() method: " + p1.getNameAndAge()); 8 9 p1.setFirstName("James"); 10 p1.setMiddleName("Earl"); 11 p1.setLastName("Brown"); 12 p1.setBirthday(1932, 8, 9); 13 14 System.out.println(p1.getFullName() + " - " + p1.getGender()); 15 System.out.println(p1.getFirstName() + " is " + p1.getAge() + " years old!"); 16 System.out.println("Testing getNameAndAge() method: " + p1.getNameAndAge()); 17 18 } // end main 19 }// end PeopleManagerApplication class
![]() |
Figure 9-9: Results of Running Example 9.11
Abstract data types can be incrementally built and tested by iteratively applying the steps of the development cycle. Start with the class definition shell and then add fields and methods as required to fulfill the class’s design objectives.
Class functionality can be testing with the help of a test driver. A test driver is a small program that’s used to exercise the functionality of another program.