Welcome to Lesson 14!

Learning Objectives
By the end of today's class, you should know...
  • What is an interface?
  • What is the purpose of an interface?
  • What is the difference between an abstract class and an interface?
  • What is the Comparable Interface and what is the proper way to override compareTo for a class?

1. Interfaces

Introduction to Interfaces

  • An interface is a group of related method signatures which provide a guarantee of the behavior a class will provide.
  • For example:
public interface MyInterface {
    //constant variables

    //method signatures
    public void myMethod1();
    public void myMethod2();
}
  • A Java interface declares a set of methods that an object must define
  • An interfaces can be considered a contract that a class is guaranteeing to uphold
  • This contract is that any class that implements the interface must define all the methods in interface
    • None of the methods in the interface have a body*
      • (*unless they are defined to be default or static (a new feature since Java 8))
    • All interface methods are implicitly public and abstract 
      • (*unless they are defined to be default or static (a new feature since Java 8))
      • Thus, you can omit the modifiers public and abstract from your method signatures
    • Any class that implements an interface must define the bodies of all the abstract methods contained in the interface.
  • In addition, an interface may define constant variables.
    • If you declare a variable inside of an interface, that variable automatically become public, static and final -- even if you do not explicitly declare it to be so.
    • Thus, you can omit the modifiers public, static and final from your variable declaration.
  • To inherit from an interface, you must use the keyword implements
public class MyClass implements MyInterface {
  • When a class implements an interface there is a formal guarantee about the behavior it will provide
  • If a class implements an interface, all methods defined by that interface must appear in its source code before the class will compile.
  • The next example shows an interface for a programmer-defined system with a method that any object must implement for drawing

Example Interface

  • Here is an example of a simple interface:
    public interface Drawable {
        public static final int FILLED = 0;
        public static final int UNFILLED = 1;
        public void draw();
    }
    
  • Provides two integer constants
  • Declares a single abstract method named draw()
  • Note that the interface does not provide any code for the method
  • An interface can only provide a method signature (unless using the keyword default as described below)

Example Interface Implementation

  • A class that implements an interface must:
    1. Declare that it is implementing the interface
      implements Drawable
    2. Provide code for all the methods of the interface
  • Here is an example class implementing the Drawable interface shown above:
    class Shape implements Drawable {
        public void draw() {
            System.out.println("Drawing a Shape.");
        }
    }
    

Writing Custom Interfaces

  • Declaring an interface is similar to declaring a class
  • You use the keyword interface instead of class
  • General syntax:
    public interface InterfaceName {
        [public] [static] [final] dataType CONSTANT_NAME = value;
        returnType methodName(parameterList);
    }
    
  • Where:
    • InterfaceName: the name you make up for the interface
    • dataType: the type of constant
    • CONSTANT_NAME: the name you make up for the constant
    • value: the value of the constant
    • returnType: the type of value returned by the method, or void for no return value
    • methodName: the name you make up for the method
    • parameterList: the types and names of the parameters
  • The constant variables and abstract methods are optional
  • For example:
    public interface Drawable {
        public static final int FILLED = 0;
        public static final int UNFILLED = 1;
        public void draw();
    }
    
  • Declares an abstract method named draw()
    • You cannot write the implementation of the method in the interface
    • Instead, you write the implementation of the method in any class that implements the interface
  • All methods are public and abstract by default
  • Similarly, all constants are public static final by default:
    • Using the keywords public static final is optional
    • Though optional, they help to document the scope
  • Any interface method that is implemented becomes an instance method

Extending Interfaces

  • You can derive new interfaces from an existing one just like classes can extend classes
  • One difference is that an interface can extend multiple interfaces
  • Syntax:
    public interface InterfaceName
        [extends SuperInterface1 [, SuperInterface2]...] { }
    
  • Where:
    • InterfaceName: the name you make up for the interface
    • SuperInterfaceX: the name of the interface being extended
  • For example, we could split our Drawable interface into two superinterfaces and one subinterface
  • The superinterfaces now contain the constants:
    interface DrawingConstants {
        public static final int FILLED = 0;
    }
    
    interface DrawingConstants2 {
        public static final int UNFILLED = 1;
    }
    
  • The subinterface contains the method declaration:
    interface Drawable
            extends DrawingConstants, DrawingConstants2 {
        public void draw();
    }
    
  • The new Drawable has the same capabilities as the old Drawable


Implementing Interfaces

  • Any class can choose to implement zero or more interfaces
  • Syntax:
    public class ClassName [extends SuperClass]
        [implements Interface1 [, Interface2]...] { }
    
  • Where:
    • ClassName: the name you make up for the class
    • SuperClass: the name of the parent class
    • InterfaceX: the name of the interface being implemented
  • Classes implementing an interface add the keyword implements in the class header
  • After the implements keyword, code a comma-delimited list of interface names
  • For example:
    public class Map implements Drawable
    
  • Class Map must now implement the method draw()
  • Note that you can refer to a constant declared in the interface without the interface name if you implement the interface
    int filled = UNFILLED;
  • A class that implements an interface must implement all methods of the interface:
    public class Map implements Drawable {
        int filled = UNFILLED;
        public void draw() {
            System.out.println("Drawing a Map.");
        }
    }
    

Abstract Classes vs. Interfaces

  • Abstract classes and interfaces have many similarities and differences
  • Both abstract classes and interfaces allow you to define constants
  • In addition, both abstract classes and interfaces allow you to declare abstract methods
  • These similarities mean that interfaces can sometimes be used instead of an abstract class

Advantages of an Abstract Class

  • An abstract class can have instance variables while an interface cannot
  • An abstract class can define regular methods while interfaces cannot

Advantages of an Interface - Multiple Inheritance

  • In Java, a class can only inherit from (extend) one class to avoid what is known as the "diamond problem" or sometimes "the deadly diamond of death" (Yikes!)
  • The diamond problem can occur when two classes define methods with identical signatures
  • If a subclass inherits from both these classes and tries to invoke one of the two methods, it will not be clear which method should be invoked (the one defined in the first class or the second class)
  • However, a class can directly implement many interfaces
    • Because (most) methods in interfaces are abstract, and thus have no bodies, it will be the job of any class extending the interface to define the body of the method
  • Additionally, interfaces can inherit from other interfaces
  • Recall that to inherit from more than one interface, a class can give a comma-separated list of interfaces in its signature, and use the keyword implements
public class MyClass implements MyInterface1, MyInterface2, MyInterface3 {
  • Similarly, an interface can provide a comma-separated list of other interfaces from which it inherits
public interface MyInterface extends MyInterface1, MyInterface2, MyInterface3 {
both classes and interfaces can inherit from more than one interface

When Will You Need Interfaces?

  • You often need to implement interfaces in the Java API
  • In particular, interfaces are used in coding graphical user interfaces
  • You design interfaces most often when creating larger applications


Default and Static Methods

  • Since Java 8, interfaces can also define methods with bodies.
  • These methods must be declared using the keyword default or static
  • The reason behind the inclusion of these methods was to allow interfaces to more easily adapt and evolve over time, and allow for backwards compatibility.
  • Assuming you have defined an interface called Trained:
public interface Trained {
    boolean canSit();
    boolean canStay();
    boolean canShake();
}
  • Any class that implements Trained must define the body of all of its abstract methods or these classes will not compile.
  • Therefore, if you later decide to add another method...
boolean canLieDown();
  • ... any class that implements your interface will now break - and you will have to deal with a number of angry programmers
  • To allow interfaces more to easily to evolve over time, Java 8 allowed default and static methods.
  • Now, a new method can be added to an interface as long as it is declared either default or static and its body defined.
    • All classes implementing the interface will automatically inherit the method with its full definition
default boolean canLieDown() {
    System.out.println("Lying down");
    return true;
}

  • With the introduction of these default and static methods, Java risked opening itself up to the Diamond Problem.
    • To resolve this problem, if a class is implementing two interfaces containing a method with the same signature and at least one of these methods is default or static method, the Java compiler requires that the class implementing the interfaces overload the method causing the problem.
    • The overloaded method definition takes precedence over any default or static implementation, thus removing the source of confusion.
  • In Effective Java, Joshua Bloch states that default methods are "risky" and advises against adding any new methods to interfaces once the interface has been released.
    • He states that when you write an interface, it should be "designed for posterity"
    • I won't cover default methods, as we will not be using them in our assignments. However, you can read more information about them here and here.


More Information



Activity 14.1: Accounts Payable Interface (10 pts)

  • Open the Address.java and Employee.java classes
  • Next, write over the contents of your Employee.java file with the following code:
/**
 * Employee.java
 * @author
 * CIS 36B, Activity 14.1
 */

import java.util.Scanner;

public abstract class Employee extends Person {
    private static int numEmployees = 0;
    private String department;
    private double salary;
   
    /**
     * Default constructor for the
     * Employee class. Calls the
     * default constructor of the
     * superclass and also initializes
     * salary and department to default
     * values
     */
    public Employee() {
        super();
        salary = 0.0;
        department = "department unknown";
    }
   
    /**
     * Multi-argument constructor for the
     * Employee class. Calls the
     * multi-argument constructor of the
     * superclass and also initializes
     * salary and department to the
     * specified values
     */
    public Employee(String name, int age, String gender, Address a, double salary, String department) {
        super(name, age, gender, a);
        this.salary = salary;
        this.department = department;
    }
   
    /**
     * Returns the annual salary
     * @return the salary
     */
    public double getSalary() {
        return salary;
    }
   
    /**
     * Returns the department
     * of the employee in the company
     * @return the department
     */
    public String getDepartment() {
        return department;
    }
   
    /**
     * Returns the total number of employees
     * @return the number of employees
     */
    public static int getNumEmployees() {
        return numEmployees;
    }
   
    /**
     * Updates the salary with a new value
     * @param salary the new salary
     */
    public void setSalary(double salary) {
        this.salary = salary;
    }
   
    /**
     * Updates the department of the employee
     * @param department the new department
     */
    public void setDepartment(String department) {
        this.department = department;
    }
   
    /**
     * Increments numEmployees
     */
    public static void updateNumEmployees() {
        numEmployees++;
    }
   
    /**
     * Defines how this category of employee
     * works
     */
    public abstract void doesWork();
   

    /**
     * To String method for an employee
     * Calls the toString method of the
     * superclass and also appends the department
     * and salary information
     */
    @Override public String toString() {
        return super.toString()
                + "\nSalary: $" + salary
                + "\nDepartment: " + department;
    }
   
    /**
     * Determines whether this is equal
     * to another Object by comparing their name,
     * types and subsequently, their name, age, gender
     * and address
     * @return whether two Objects are equal
     */
    @Override public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (! (o instanceof Employee)) {
            return false;
        } else {
            Employee e = (Employee) o;
            return (super.equals(o)
                    && salary == e.salary
                    && department.equals(e.department));
        }
    }
}

  • Notice that this class has now been made abstract, and contains an abstract method doesWork()
  • Next, create two subclasses of Employee - Manager.java and Programmer.java.
  • Copy and paste the below code into the Manager.java file and write the given methods:
/**
 * Manager.java
 * @author
 * CIS 36B, Activity 14.1
 */
public class Manager extends Employee {
    private String title;
    private static double taxBracket = .32;
   
    /** Constructors **/
   
    /**
     * Assigns default values to all fields
     * by calling the 7-argument constructor
     * name: name unknown
     * age: 0
     * gender: gender unknown
     * address: null
     * salary: 0.0
     * department: department unknown
     * title: title unknown
     */
    public Manager() {
       
    }
   
    /**
     * Calls 6-argument constructor of the super class
     * and assigns title
     * @param name the manager name
     * @param age the manager age
     * @param gender the manager gender
     * @param a the manager address
     * @param salary the manager salary
     * @param department the manager department
     * @param title the manager title
     */
    public Manager(String name, int age,
            String gender, Address a,
            double salary, String department,
            String title) {
       
    }
   
    /**Accessors**/
   
    /**
     * Returns the manager's title
     * @return the title
     */
    public String getTitle() {
       return "";
    }
   
    /**
     * toString method for the Manager class
     * calls the super class toString and also
     * adds Title: <title> to the String
     */
    @Override public String toString() {
        return "";
    }
   
   
    /**Mutators**/
   
    /**
     * Sets the current title of the manager
     * @param title the new title
     */
    public void setTitle(String title) {
        return;
    }
   
    /**Additional Operations**/
   
    /**
     * "does work" by printing out the message
     * Work: Telling people what to do
     */
    public void doesWork() {
        return;
    }
   
   
}

  • Copy and paste the below code into Programmer.java and implement the given methods:
/**
 * Programmer.java
 * @author
 * CIS 36B, Activity 14.1
 */
public class Programmer extends Employee {
    private String assignedProject;
    private static double taxBracket = .24;
   
    /**Constructors**/
   
    /**
     * Assigns default values to all fields
     * by calling the 7-argument constructor
     * name: name unknown
     * age: 0
     * gender: gender unknown
     * address: null
     * salary: 0.0
     * department: department unknown
     * assignedProject: project unknown
     */
    public Programmer() {
       
    }
   
    /**
     * Calls constructor of the super class
     * and assigns project
     * @param name the manager name
     * @param age the manager age
     * @param gender the manager gender
     * @param a the manager address
     * @param salary the manager salary
     * @param department the manager department
     * @param project the assigned project
     */
    public Programmer(String name, int age,
            String gender, Address a,
            double salary, String department,
            String project) {
       
    }
   
    /**Accessors**/
   
    /**
     * Returns the title of the programmer's
     * currently assigned project
     * @return the assigned project title
     */
    public String getAssignedProject() {
        return "";
    }
   
   
    /**
     * toString method for the Manager class
     * calls the superclass toString and also
     * adds Project: <assignedProject> to the String
     */
    @Override public String toString() {
        return "";
    }
   
    /**Mutators**/
   
    /**
     * Sets the assigned project
     * @param project the new project
     */
    public void setAssignedProject(String project) {
        return;
    }
   
    /**Additional Operations**/
   
   
    /**
     * "does work" by printing out the message
     * Work: Writing code
     */
    public void doesWork() {
        return;
    }
}

  • Next, add an Interface (File->New->Interface) to your project called AccountsPayable.java
  • Copy and paste the below code into your file:
/**
 * AccountsPayable.java
 * @author
 * CIS 36B, Activity 14.1
 */
public interface AccountsPayable {
   
    double salaryAfterTaxes();
    void printPayCheck();
}
  • Now, update Manager.java and Programmer.java so that they implement the AccountsPayable interface.
  • You should not get an error message for these two classes as they must define the methods defined in AccountsPayable.java in order to compile.
  • Add the following comment and method signature to Manager.java under the Accessors section of the class:
    /**
     * Calculates the net salary after taxes
     * net salary = gross salary * (1 - taxBracket)
     * @return the net salary
     */
   
@Override public double salaryAfterTaxes() {
        return 0.0;
    }
  • Then, write the method body as described in the comment.
  • Next, add the following comment and method signature to Manager.java in the Additional Operations section of the class:
    /**
     * Prints out address to mail the paycheck
     * Mail to:
     * Title + Name
     * Address
     */
   
@Override public void printPayCheck() {
        System.out.println("Mail to:");
       
    }
  • Now implement the rest of the method body.
  • In Programmer.java, add the following comment and method to the Accessor section of the class, and then fill in the method body:
    /**
   * Calculates the net salary after taxes
   * net salary = gross salary * (1 - taxBracket)
   * @return the net salary
   */
    @Override public double salaryAfterTaxes() {
        return 0.0;
    }
  • Finally, add the following comment and method to the Additional Operations section of the Programmer class, and then fill in the method body:
    /**
     * Prints out the correct address to mail the
     * paycheck, in the format:
     * Mail to:
     * Mr./Ms./Mx. (note use if statements here)
     * Name
     * Address
     */
   
@Override public void printPayCheck() {
        System.out.println("Mail to:");
       
    }
  • Lastly, write over your EmployeeTest.java file with the following code:
/**
 * EmployeeTest.java
 * @author
 * CIS 36B, Activity 14.1
 */

import java.util.Scanner;

public class EmployeeTest {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        String name, gender, street, department, title, project;
        int age, number;
        double salary;
        Manager employee1 = null;
        Programmer employee2 = null;
    
        System.out.print("Welcome, Manager!\n\nEnter your name: ");
        name = input.nextLine();
      
        System.out.print("Enter your age: ");
        age = input.nextInt();
      
        System.out.print("Enter your gender (M/F/O): ");
        gender = input.next();
       
        System.out.print("Enter the street number of your address: ");
        number = input.nextInt();
      
        System.out.print("Enter the name of the street: ");
        input.nextLine();
        street = input.nextLine();
       
        Address address = new Address(number, street);
       
        System.out.print("Enter your department in the company: ");
        department = input.nextLine();
       
        System.out.print("Enter your title: ");
        title = input.nextLine();
       
        System.out.print("Enter your annual salary ($150,000-200,000): $");
        salary = input.nextDouble();
       
      
        employee1 = new Manager(name, age, gender, address, salary, department, title);
       
        System.out.println("\nWhat you did at work today:");
        employee1.doesWork();
       
        System.out.format("\nGreat job!\n\n"
                + "After taxes this year, you earned: $%.2f\n\n",
                 employee1.salaryAfterTaxes());
       
        System.out.println("Cutting your paycheck...\n");
        employee1.printPayCheck();
       
             
        System.out.print("\nWelcome Programmer!\nEnter Your Name: ");
        input.nextLine();
        name = input.nextLine();
      
        System.out.print("Enter your age: ");
        age = input.nextInt();
      
        System.out.print("Enter your gender (M/F/O): ");
        gender = input.next();
       
        System.out.print("Enter the street number of your address: ");
        number = input.nextInt();
      
        System.out.print("Enter the name of the street: ");
        input.nextLine();
        street = input.nextLine();
       
        Address address2 = new Address(number, street);
       
        System.out.print("Enter your department in the company: ");
        department = input.nextLine();
       
        System.out.print("Enter the name of project you are working on: ");
        project = input.nextLine();
       
        System.out.print("Enter your annual salary ($110,000-150,000): $");
        salary = input.nextDouble();
       
       
        employee2 = new Programmer(name, age, gender, address2, salary, department, project);
       
        System.out.println("\nWhat you did at work today:");
        employee2.doesWork();
       
        System.out.format("\nGreat job!\n\n"
                + "After taxes this year, you earned: $%.2f\n\n",
                 employee2.salaryAfterTaxes());
       
        System.out.println("Cutting your paycheck...\n");
        employee2.printPayCheck();
      
        input.close();

    }
}
  • When your program works identically to what is shown in the sample output below, submit Employee.java, Manager.java, and Programmer.java to Canvas.

Sample Output:


Welcome, Manager!

Enter your name: Jacqueline Nguyen
Enter your age: 47
Enter your gender (M/F/O): F
Enter the street number of your address: 555
Enter the name of the street: Richie Rich St
Enter your department in the company: Research and Development
Enter your title: Engineering Manager
Enter your annual salary ($150,000-200,000): $189000

What you did at work today:
Work: Telling people what to do.

Great job!

After taxes this year, you earned: $128520.00

Cutting your paycheck...

Mail to:
Engineering Manager Jacqueline Nguyen
555 Richie Rich St

Welcome Programmer!
Enter Your Name: Ichiro Yamamoto
Enter your age: 42
Enter your gender (M/F/O): M
Enter the street number of your address: 4321
Enter the name of the street: Pacific Palisades Dr
Enter your department in the company: Research and Development
Enter the name of project you are working on: Rocket Launch Interface
Enter your annual salary ($110,000-150,000): $135000

What you did at work today:
Work: Writing code.

Great job!

After taxes this year, you earned: $102600.00

Cutting your paycheck...

Mail to:
Mr. Ichiro Yamamoto
4321 Pacific Palisades Dr


2. Implementing the Comparable Interface and the CompareTo Method

The Comparable Interface

  • Unlike equals, the compareTo method is not defined as part of the Object class, but rather is the sole abstract method in the Comparable Interface:
public interface Comparable<T> {
    int compareTo(T t);
}
  • To define the compareTo method for your class, you must implement the Comparable Interface.
  • For example,
public class Dog implements Comparable<Dog> {
  • Notice that the Comparable interface is generic - a topic we will discuss in detail next class - and we are, thus, required to put the type of Object to compare inside of the angled brackets: <Dog>

Defining compareTo() for a Class

The compareTo() Contract:

  • Once the signature for a class has been updated to implement the Comparable interface, we are now required to define compareTo or the class will not compile
  • When writing the compareTo method it is important to be mindful of the "compareTo Contract," as follows:
    • The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)
    • The implementor must also ensure that the relation is transitive: (x.compareTo(y) > 0 && y.compareTo(z) > 0) implies x.compareTo(z) > 0.
    • Finally, the implementor must ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.
where, the notation sgn(expression) above designates the mathematical signum function, which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero, or positive, respectively.
  • Note that Oracle strongly recommends that the equals and compareTo methods correspond, such that if x.equals(y) then x.compareTo(y)==0. However, it is not a requirement of the method (and should be noted in the comments for the method that there is an irregular comparison)

Writing compareTo()

  • When writing compareTo, the type of Object passed in as a parameter must match that of the type in <> in the class signature.
public class Dog implements Comparable<Dog> {
    private String name;
    private int age;

    @Override public int compareTo(Dog d) {
        //method body
    }
}

  • The best approach to writing this method is to start by comparing the most significant field (i.e. name for the Dog class)
  • If these two fields are equal, then compare the next most significant field (i.e. age), and so on until you find an unequal field
  • I would recommend calling the equals method as a first step to determine whether the two objects are equal.
  • Below is an example of a compareTo method for the Dog class:
public class Dog implements Comparable<Dog> {
    private String name;
    private int age;

    @Override public int compareTo(Dog d) {
        if (this.equals(d)) {
            return 0;
        } else if (!(name.equals(d.name))) { //names not equal, compare names
            return name.compareTo(d.name);
        } else { //names are equal, compare ages
            return Integer.compare(age, d.age);
        }
    }
    }
  • Two important notes:
  1. In the above implementation, I made use of the compareTo method already defined for String, and return this value in the case that the names were unequal.
  2. Additionally, as recommended by Joshua Bloch in Effective Java, I made use of the static compare method of the Integer class to determine an appropriate value to return when comparing the two ints. These static comparison methods are considered preferable (and less verbose) to the use of < and > operators that might otherwise be used to compare primitive types.
  • Here is another example:
public class Dog implements Comparable<Dog> {
    private String name;
    private int age;
    private boolean isChildFriendly;

    @Override public int compareTo(Dog d) {
        if (this.equals(d)) {
            return 0;
        } else if(!(name.equals(d.name))) { //names not equal, compare names
        return name.compareTo(d.name);
    } else if (age != d.age) {
        return Integer.compare(age, d.age);
    } else {
        return Boolean.compare(isChildFriendly, d.isChildFriendly);
    }
    }
    }


Activity 14.2: Sorting Employees (10 pts)

  • Open up Address.java, Employee.java and EmployeeTest.java from the last activity
  • Next, alter the signature for the Address class to implement the Comparable interface.
  • Add the following method signature to Address, and implement compareTo as described in the comment:
/**
     * Compares two addresses and returns
     * an integer value: 0 if equal addresses
     * negative if this address comes before a
     * positive if this address comes after a
     * To determine ordering, sorts first by street
     * name and second by street number
     */
    @Override public int compareTo(Address a) {
        return -1;
    }
  • You can now close Address.java.
  • Inside of Employee.java, alter the class signature so that it implements the Comparable interface.
  • Add the following method signature to the Employee.java class and implement compareTo as described in the comment:
/**
     * Compares two Employees and returns
     * an integer value: 0 if equal Employees
     * negative if this Employee comes before e
     * positive if this Employee comes after e
     * To determine ordering, sorts first by name,
     * next by age, next by gender, next by address,
     * next by department and finally by salary
     */
    @Override public int compareTo(Employee e) {
        return -1;
    }
  • You can now close Employee.java
  • Finally, replace EmployeeTest.java with the following code:
/**
 * EmployeeTest.java
 * @author
 * CIS 36B, Activity 14.2
 */

import java.util.Scanner;
import java.util.ArrayList;

public class EmployeeTest {
    private ArrayList<Employee> employees = new ArrayList<Employee>();
    public static void main(String[] args) {
        EmployeeTest t = new EmployeeTest();
        t.employees.add(new Manager("Jacqueline Nguyen",
                47, "F", new Address(555, "Richie Rich St"), 189000,
                "Research and Development", "Engineering Manager"));
        t.employees.add(new Programmer("Ichiro Yamamoto",
                42, "M", new Address(4321, "Pacific Palisades Dr"), 135000,
                "Research and Development", "Rocket Launch Interface"));
        t.employees.add(new Manager("Sanjiv Sardar",
                65, "M", new Address(445, "Howard St"), 175000,
                "Marketing", "Communications Manager"));
        System.out.println("Before Sorting:\n");
        t.printEmployees();
        t.bubbleSort();
        System.out.println("\n\nAfter Sorting:\n");
        t.printEmployees();
    }
   
    public void printEmployees() {
        for (int i = 0; i < employees.size(); i++) {
            System.out.println(employees.get(i) + "\n");
        }
    }
   
    public void bubbleSort() {
        for (int i = 0; i < employees.size() - 1; i++) {
            for (int j = 0; j < employees.size() - i - 1; j++) {
                if (employees.get(j).compareTo(employees.get(j + 1)) > 0) {
                    //Fill in here!
                }
            }
        }
    }
}
  • Complete the implementation of BubbleSort
  • When you are finished, run the program and verify that you get the output as shown in the example output below.
  • Then, upload Address.java, Employee.java, and EmployeeTest.java to Canvas

Sample Output:

Before Sorting:

Name: Jacqueline Nguyen
Age: 47
Gender: F
Address: 555 Richie Rich St
Salary: $189000.0
Department: Research and Development
Title: Engineering Manager

Name: Ichiro Yamamoto
Age: 42
Gender: M
Address: 4321 Pacific Palisades Dr
Salary: $135000.0
Department: Research and Development
Project Rocket Launch Interface

Name: Sanjiv Sardar
Age: 65
Gender: M
Address: 445 Howard St
Salary: $175000.0
Department: Marketing
Title: Communications Manager



After Sorting:

Name: Ichiro Yamamoto
Age: 42
Gender: M
Address: 4321 Pacific Palisades Dr
Salary: $135000.0
Department: Research and Development
Project Rocket Launch Interface

Name: Jacqueline Nguyen
Age: 47
Gender: F
Address: 555 Richie Rich St
Salary: $189000.0
Department: Research and Development
Title: Engineering Manager

Name: Sanjiv Sardar
Age: 65
Gender: M
Address: 445 Howard St
Salary: $175000.0
Department: Marketing
Title: Communications Manager


Wrap Up: 

  • Answer the Lesson 14 Practice Exam Questions on Canvas

Upcoming Assignments:

  • Activity 14.1 and 14.2 due Thursday at 11:59pm
  • Lesson 14 Practice Exam Questions due Thursday at 11:59pm
  • Peer Reviews of Lesson 13 and 14 Practice Exam Questions due Saturday at 11:59pm
  • Quiz 5 due Friday at 11:59pm
  • Lab 7 due Monday at 11:59pm


~ Have a Great Weekend! ~