Big Java / Java Concepts Lab 11

Implementing an Interface

1.

The Comparable interface is a commonly used interface in Java. Look up the Comparable interface in the API documentation.

If you wanted to modify the BankAccount class so that it implements the Comparable<BankAccount> interface, what method(s) do you need to implement?

Give the method signatures, that is, the return type(s), the method name(s), and the method parameter(s).


2.

The compareTo method compares two parameters, the implicit and explicit parameter. The call

a.compareTo(b)

returns

  • 1 if a is larger than b
  • -1 if a is smaller than b
  • 0 if a and b are the same

Implement the compareTo method of the BankAccount class so that it compares the balances of the accounts. Some of the code has been provided for you:


public class BankAccount implements Comparable<BankAccount>

{
    . . .

    /**
        Compares two bank accounts.
        @param other the other BankAccount
        @return 1 if this bank account has a greater balance than the other one,
        -1 if this bank account is has a smaller balance than the other one,
        and 0 if both bank accounts have the same balance
    */
    public int compareTo(BankAccount other)
    {
        . . .
    }

    private double balance;
}


3.

The sort method of the Collections class can sort a list of objects of classes that implement the Comparable interface.

Here is the outline of the required code.


import java.util.ArrayList;
import java.util.Collections;
. . .

// put bank accounts into a list
ArrayList<BankAccount> list = new ArrayList<BankAccount>();
list.add(ba1);
list.add(ba2);
list.add(ba3);

// call the library sort method
Collections.sort(list);

// print out the sorted list
for (BankAccount b : list) 
   System.out.println(b.getBalance());

Using this outline, write a test program that sorts a list of five bank accounts.

Enter your test program here.


4.

What is the outcome of executing your test program? Remember that you must use the version of the BankAccount class that implements the Comparable interface.


5.

Change your compareTo method by switching the return values 1 and -1. Recompile and run the test program again. What is the outcome of executing your test program? Explain the changed output.

Using Interfaces for Callbacks

6.

Modify the test program so that it sorts Rectangle objects:

Rectangle rect1 = new Rectangle(5, 10, 20, 30);
Rectangle rect2 = new Rectangle(10, 20, 30, 15);
Rectangle rect3 = new Rectangle(20, 30, 45, 10);

// put the rectangles into a list
ArrayList<Rectangle> list = new ArrayList<Rectangle>();
list.add(rect1);
list.add(rect2);
list.add(rect3);

// call the library sort method
Collections.sort(list);

// print out the sorted list
for (Rectangle r : rectangles)
    System.out.println(r.getWidth() + " " + r.getHeight());

When you run the program, you will get an error message. What is the error message? What is the reason for the error message?


7.

Unfortunately, you cannot modify the Rectangle class so that it implements the Comparable interface. The Rectangle class is part of the standard library, and you cannot modify library classes.

Fortunately, there is a second sort method that you can use to sort a list of objects of any class, even if the class doesn't implement the Comparable interface.


Comparator<Rectangle> comp = . . .; 

Collections.sort(list, comp);

Comparator is an interface. Therefore, comp must be constructed as an object of some class that implements the Comparator interface.

What method(s) must that class implement? (Hint: Look up the Comparator interface in the API documentation.)


8.

Implement a class RectangleComparator whose compare method compares two rectangles.

Return

  • 1 if the area of the first rectangle is larger than the area of the second rectangle
  • -1 if the area of the first rectangle is smaller than the area of the second rectangle
  • 0 if the two rectangles have the same area

What is the code for your RectangleComparator class?

Part of the code has been provided for you below:

import java.util.Comparator;
import java.awt.Rectangle;

public class RectangleComparator implements Comparator<Rectangle>
{
    /**
    Compares two Rectangle objects.
    @param r1 the first rectangle
    @param r2 the second rectangle
    @return 1 if the area of the first rectangle is larger than the area of
    the second rectangle, -1 if the area of the first rectangle is
    smaller than the area of the second rectangle or 0 if the two
    rectangles have the same area
*/
    public int compare(Rectangle r1, Rectangle r2)
    {
        . . .
    }
}


9.

Write a test program that adds the three rectangles given previously to a list, constructs a rectangle comparator, sorts the list, and prints the sorted list.

What is your test program?


10.

What is the output of your test program?


11.

A very specialized class, such as the RectangleComparator, can be defined inside the method that uses it.

Reorganize your program so that the RectangleComparator class is defined inside the main method of your test class.

What is your main method now?

Event Handling

12.

A timer notifies a listener at regular time intervals. The time interval is given in milliseconds. The listener must implement the ActionListener interface.

For example, the call


Timer t = new Timer(1000, listener);

t.start();

causes the timer to call the actionPerformed method once per second.

To see the timer at work, install a listener that simply prints out the current time. To print out the current time call


import java.util.Date;

. . .
System.out.println(new Date());

Supply a class CurrentTimePrinter that implements the ActionListener interface and whose actionPerformed method prints the current time.

What is the code for the CurrentTimePrinter class?


13.

Now put together a test program that prints the current time once each second.

Construct a CurrentTimePrinter, construct and start a timer, and put up a message dialog so that the program user can quit the program.


JOptionPane.showMessageDialog(null, "Quit?");

System.exit(0);

What is your test program?.


14.

The program of the preceding exercise keeps printing the time, once per second. In this exercise, you will modify the program so that it stops the timer after 15 seconds, restarts it after another 15 seconds, stops it after a further 15 seconds, and so on.

Of course, we will use a second timer for this purpose. Here is the implementation:


class TimerToggler implements ActionListener

{
    public void actionPerformed(ActionEvent event)
    {
        if (t.isRunning())
            t.stop();
        else
            t.restart();
     }
}

ActionListener listener2 = new TimerToggler();
Timer t2 = new Timer(15000, listener2);

t2.start();

Add the code that defines t2 after the instruction for starting t and before displaying the option pane. Compile the code.

What compiler error do you get? Why? What can you do to avoid it?


15.

Fix your program so that the first timer is declared as final. Methods of inner classes can access only final local variables of the enclosing method.

Your program should now compile and run. Execute it for approximately one minute. What output do you get?


16.

It is a nuisance that the user must stop the program by clicking a button. Solve that problem by automatically stopping the program after two minutes (or 120,000 milliseconds). Simply make a timer listener that calls System.exit(0) in the actionPerformed method of its action listener.

Write the code for the third timer.


17.

Now add the code for your third timer to the program and remove the last two lines of main, that is, the message dialog display and the call to System.exit(0).

Compile your program and run it.

Does it work as expected? If not, why?


18.

The program exited immediately when exiting main, so the timers never ran.

To keep main alive, you'll need to add the message dialog back in. Simply add the line

JOptionPane.showMessageDialog(null, "Please wait");

to the end of main.

Now the program will run for two minutes, and then exit. What output do you get?