Payroll Using Generics - Exercise

Contact Us or call 1-877-932-8228
Payroll Using Generics - Exercise

Payroll Using Generics

Duration: 15 to 25 minutes.

We can modify our payroll application to use generic lists instead of arrays for our employees, invoices, and payables.

  1. Make the Employee[] variable a List<Employee>, and populate it with a new ArrayList<Employee>.
  2. Since lists have no fixed size, you will need to change the first for loop, perhaps to a fixed number of iterations.
  3. Modify the lines that add employees from using array indices to using the add method.
  4. Turn the Invoice[] into a List<Invoice> populated with a Vector<Invoice>, similar to what we did in we did in step 1.
  5. Modify the lines that populate that list.
  6. Create an ArrayList<Payable> in a List<Payable> payables variable.
  7. Create an ArrayList<Payable> in a List<Payable> payments variable.
  8. Then call that list's addAll method once and pass in the employee list.
  9. Then add all the invoices the same way.
  10. Since we might not want to modify CheckPrinter, you can generate a Payable array for it with:
    CheckPrinter.printChecks( payments.toArray(new Payable[] { }) ); 
    The parameter is a "dummy" array used to tell the generic method what type of array to create. Note in the Collection documentation that this method is typed with T rather than the E used in the rest of the class. This method has its own local type, which is determined by the type of the array passed in.

Solution:

Solutions/Payroll-Collections01/Payroll.java
import employees.*;
import vendors.*;
import util.*;
import finance.*;
import java.util.*;

public class Payroll {	
	public static void main(String[] args) {
		List<Employee> e = new ArrayList<Employee>();
		Employee empl = null;
		String fName = null;
		String lName = null;
		int dept = 0;
		double payRate = 0.0;
		double hours = 0.0;

		for (int i = 0; i < 5; i++) {
			try {
 				char type = 
					KeyboardReader.getPromptedChar("Enter type: E, N, or C: ");
				if (type != 'e' && type != 'E' && 
						type != 'n' && type != 'N' && 
						type != 'c' && type != 'C') {
					System.out.println("Please enter a valid type");
					i--;
					continue; 			 
				}
				fName = KeyboardReader.getPromptedString("Enter first name: ");
				lName = KeyboardReader.getPromptedString("Enter last name: ");
	      dept = KeyboardReader.getPromptedInt(
	      			"Enter department: ", "Department must be numeric",
	      			new DeptValidator(), "Valid departments are 1 - 5");
				do {
					payRate = KeyboardReader.getPromptedDouble("Enter pay rate: ", 
									"Pay rate must be numeric");
					if (payRate < 0.0) System.out.println("Pay rate must be >= 0");
				} while (payRate < 0.0);
	
				switch (type) {
					case 'e':
					case 'E': 
						empl = new ExemptEmployee(fName, lName, dept, payRate);
						e.add(empl);
						break;
					case 'n':
					case 'N': 
						do {
							hours = KeyboardReader.getPromptedDouble("Enter hours: ");
							if (hours < 0.0) 
								System.out.println("Hours must be >= 0");
						} while (hours < 0.0);
						empl = new NonexemptEmployee(fName,lName,dept,payRate,hours);
						e.add(empl);
						break;
					case 'c':
					case 'C': 
						do {
							hours = KeyboardReader.getPromptedDouble("Enter hours: ");
							if (hours < 0.0) 
								System.out.println("Hours must be >= 0");
						} while (hours < 0.0);
						empl = new ContractEmployee(fName,lName,dept,payRate,hours);
						e.add(empl);
				}
 
				System.out.println(empl.getPayInfo());
			} catch (InvalidValueException ex) {
					System.out.println(ex.getMessage());
					i--;	//failed, so back up counter to repeat this employee
				}
		}
 	
		System.out.println();
		System.out.println("Exempt Employees");
		System.out.println("====== =========");
		for (Employee emp : e) {
			if (emp instanceof ExemptEmployee) {
				System.out.println(emp.getPayInfo());
			}
		}
		System.out.println();
		System.out.println("Nonexempt Employees");
		System.out.println("======== =========");
		for (Employee emp : e) {
			if (emp instanceof NonexemptEmployee) {
				System.out.println(emp.getPayInfo());
			}
		}
		System.out.println();
		System.out.println("Contract Employees");
		System.out.println("======== =========");
		for (Employee emp : e) {
			if (emp instanceof ContractEmployee) {
				System.out.println(emp.getPayInfo());
			}
		}

		List<Invoice> inv = new Vector<Invoice>();
		inv.add(new Invoice("ABC Co.", 456.78));
		inv.add(new Invoice("XYZ Co.", 1234.56));
		inv.add(new Invoice("Hello, Inc.", 999.99));
		inv.add(new Invoice("World, Ltd.", 0.43));

		List<Payable> payments = new ArrayList<Payable>();
		payments.addAll(e);
		payments.addAll(inv);

		CheckPrinter.printChecks( payments.toArray(new Payable[] { }) );
	}
}

Notice that we didn't have to change the for-each loops; they work equally well for Iterable objects, like lists, as they do for arrays.

Also, the addAll method accepts any Collection, so it can take an ArrayList or a Vector equally well. And, since it accepts Collection<? extends E>, it can take collections of either Employee or Invoice (both implement the Payable type used for E in the the receiving collection).

Next