Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Intro_Java_brief_Liang2011.pdf
Скачиваний:
195
Добавлен:
26.03.2016
Размер:
10.44 Mб
Скачать

14.5 Example: The Comparable Interface 467

Tip

A constant defined in an interface can be accessed using the syntax InterfaceName.

accessing constants

CONSTANT_NAME (e.g., T.K).

 

14.5 Example: The Comparable Interface

Suppose you want to design a generic method to find the larger of two objects of the same type, such as two students, two dates, two circles, two rectangles, or two squares. In order to accomplish this, the two objects must be comparable. So, the common behavior for the objects is comparable. Java provides the Comparable interface for this purpose. The interface is defined as follows:

// Interface for comparing objects, defined in java.lang

java.lang.Comparable

package java.lang;

 

 

 

public interface Comparable

{

 

 

public int compareTo(Object o);

 

 

}

 

 

 

 

The compareTo method determines the order of this object with the specified object o and returns a negative integer, zero, or a positive integer if this object is less than, equal to, or greater than o.

Many classes in the Java library (e.g., String and Date) implement Comparable to define a natural order for the objects. If you examine the source code of these classes, you will see the keyword implements used in the classes, as shown below:

public class String extends Object implements Comparable {

// class body omitted

}

public class Date extends Object implements Comparable {

// class body omitted

}

Thus, strings are comparable, and so are dates. Let s be a String object and d be a Date object. All the following expressions are true.

s instanceof String

 

d instanceof java.util.Date

s instanceof

Object

 

d instanceof

Object

s instanceof

Comparable

 

d instanceof

Comparable

 

 

 

 

 

A generic max method for finding the larger of two objects can be defined, as shown in (a) or (b) below:

// Max.java: Find a maximum object public class Max {

/** Return the maximum of two objects */ public static Comparable max

(Comparable o1, Comparable o2) { if (o1.compareTo(o2) > 0)

return o1; else

return o2;

}

}

// Max.java: Find a maximum object public class Max {

/** Return the maximum of two objects */ public static Object max

(Object o1, Object o2) {

if (((Comparable)o1).compareTo(o2) > 0) return o1;

else

return o2;

}

}

(a)

(b)

468 Chapter 14

Abstract Classes and Interfaces

(a) is simpler

The max method in (a) is simpler than the one in (b). In the Max class in (b), o1 is declared

 

as Object, and (Comparable)o1 tells the compiler to cast o1 into Comparable so that the

 

compareTo method can be invoked from o1. However, no casting is needed in the Max class

 

in (a), since o1 is declared as Comparable.

(a) is more robust

The max method in (a) is more robust than the one in (b). You must invoke the max method

 

with two comparable objects. Suppose you invoke max with two noncomparable objects:

 

Max.max(anyObject1, anyObject2);

 

The compiler will detect the error using the max method in (a), because anyObject1 is not

 

an instance of Comparable. Using the max method in (b), this line of code will compile fine

 

but will have a runtime ClassCastException, because anyObject1 is not an instance of

 

Comparable and cannot be cast into Comparable.

 

From now on, assume that the max method in (a) is in the text. Since strings are compara-

 

ble and dates are comparable, you can use the max method to find the larger of two instances

 

of String or Date. Here is an example:

String s1 = "abcdef";

String s2 = "abcdee";

String s3 = (String)Max.max(s1, s2);

Date d1 = new Date(); Date d2 = new Date();

Date d3 = (Date)Max.max(d1, d2);

The return value from the max method is of the Comparable type. So you need to cast it to String or Date explicitly.

You cannot use the max method to find the larger of two instances of Rectangle, because Rectangle does not implement Comparable. However, you can define a new rectangle class that implements Comparable. The instances of this new class are comparable. Let this new class be named ComparableRectangle, as shown in Listing 14.7.

LISTING 14.7 ComparableRectangle.java

 

1

public class ComparableRectangle extends Rectangle

implements Comparable

2

 

 

implements Comparable

{

 

3

 

/** Construct a ComparableRectangle with specified properties */

 

4

 

public ComparableRectangle(double width, double height) {

 

5

 

 

super(width, height);

 

6

}

 

 

 

 

7

 

 

 

 

 

 

8

/** Implement the compareTo method defined in Comparable */

implement compareTo

9

 

public int compareTo(Object o)

{

 

10

 

if (getArea() > ((ComparableRectangle)o).getArea())

 

11

 

 

return 1;

 

12

 

else if (getArea() < ((ComparableRectangle)o).getArea())

 

13

 

 

return -1;

 

14

 

else

 

15

 

 

return 0;

 

16

}

 

 

 

 

17

}

 

 

 

 

ComparableRectangle extends Rectangle and implements Comparable, as shown in Figure 14.4. The keyword implements indicates that ComparableRectangle inherits all the constants from the Comparable interface and implements the methods in the interface. The compareTo method compares the areas of two rectangles. An instance of

ComparableRectangle is also an instance of Rectangle, GeometricObject, Object, and Comparable.

14.6 Example: The ActionListener Interface 469

Notation:

The interface name and the method names are italicized. The dashed lines and hollow triangles are used to point to the interface.

GeometricObject

«interface»

 

java.lang.Comparable

 

+compareTo(o: Object): int

Rectangle

 

ComparableRectangle

 

FIGURE 14.4 ComparableRectangle extends Rectangle and implements Comparable.

You can now use the max method to find the larger of two objects of ComparableRectangle. Here is an example:

ComparableRectangle rectangle1 = new ComparableRectangle(4, 5);

ComparableRectangle rectangle2 = new ComparableRectangle(3, 6);

System.out.println(Max.max(rectangle1, rectangle2));

An interface provides another form of generic programming. It would be difficult to use a benefits of interface generic max method to find the maximum of the objects without using an interface in this

example, because multiple inheritance would be necessary to inherit Comparable and another class, such as Rectangle, at the same time.

The Object class contains the equals method, which is intended for the subclasses of the Object class to override in order to compare whether the contents of the objects are the same. Suppose that the Object class contains the compareTo method, as defined in the Comparable interface; the new max method can be used to compare a list of any objects. Whether a compareTo method should be included in the Object class is debatable. Since the compareTo method is not defined in the Object class, the Comparable interface is defined in Java to enable objects to be compared if they are instances of the Comparable interface. It is strongly recommended (though not required) that compareTo should be consistent with equals. That is, for two objects o1 and o2, o1.compareTo(o2) == 0 if and only if o1.equals(o2) is true.

14.6 Example: The ActionListener Interface

Now you are ready to write a short program to address the problem proposed in the introduction of this chapter. The program displays two buttons in the frame, as shown in Figure 14.1. To respond to a button click, you need to write the code to process the button-clicking action. The button is a source object where the action originates. You need to create an object capable of handling the action event on a button. This object is called a listener, as shown in Figure 14.5.

Not all objects can be listeners for an action event. To be a listener, two requirements must be met:

1.

The object must be an instance of the ActionListener interface. This interface

ActionListener interface

 

defines the common behavior for all action listeners.

 

2.

The ActionListener object listener must be registered with the source using the

 

 

method source. addActionListener(listener).

addActionListener

 

 

 

 

 

 

 

 

 

 

 

 

 

(listener)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

button

 

 

 

event

 

 

 

listener

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Clicking a button

An event is

The listener object

fires an action event

 

an object

processes the event

FIGURE 14.5 A listener object processes the event fired from the source object.

470 Chapter 14

Abstract Classes and Interfaces

 

The ActionListener interface contains the actionPerformed method for processing the

 

event. Your listener class must override this method to respond to the event. Listing 14.8 gives

 

the code that processes the ActionEvent on the two buttons. When you click the OK button,

 

the message “OK button clicked” is displayed. When you click the Cancel button, the mes-

 

sage “Cancel button clicked” is displayed, as shown in Figure 14.1.

 

LISTING 14.8 HandleEvent.java

 

1

import javax.swing.*;

 

2

import java.awt.event.*;

 

3

 

 

 

 

 

 

 

 

 

 

 

4

public class

HandleEvent extends JFrame

{

 

5

public HandleEvent() {

 

6

 

// Create two buttons

 

7

 

JButton jbtOK = new JButton("OK");

 

8

 

JButton jbtCancel = new JButton("Cancel");

 

9

 

 

 

 

 

 

 

 

 

 

 

10

 

// Create a panel to hold buttons

 

11

 

JPanel panel = new JPanel();

 

12

 

panel.add(jbtOK);

 

13

 

panel.add(jbtCancel);

 

14

 

 

 

 

 

 

 

 

 

 

 

15

 

add(panel); // Add panel to the frame

 

16

 

 

 

 

 

 

 

 

 

 

 

17

 

// Register listeners

create listener

18

 

OKListenerClass listener1 = new OKListenerClass();

 

 

19

 

CancelListenerClass listener2 = new CancelListenerClass();

register listener

20

 

jbtOK.addActionListener(listener1);

 

 

 

 

21

 

jbtCancel.addActionListener(listener2);

 

22

}

 

 

 

 

 

 

 

 

 

 

23

 

 

 

 

 

 

 

 

 

 

 

24

public static void main(String[] args) {

 

25

 

JFrame frame = new HandleEvent();

 

 

 

 

 

26

 

frame.setTitle("Handle Event");

 

27

 

frame.setSize(200, 150);

 

28

 

frame.setLocation(200, 100);

 

29

 

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

30

 

frame.setVisible(true);

 

31

}

 

 

 

 

 

 

 

 

 

 

32

}

 

 

 

 

 

 

 

 

 

 

33

 

 

 

 

 

 

 

 

 

 

listener class

34

class

OKListenerClass implements ActionListener

{

 

process event

35

public void actionPerformed(ActionEvent e) {

 

36

 

System.out.println("OK button clicked");

 

37

}

 

 

 

 

 

 

 

 

 

 

38

}

 

 

 

 

 

 

 

 

 

 

39

 

 

 

 

 

 

 

 

 

 

listener class

40

class

CancelListenerClass implements ActionListener

{

 

process event

41

public void actionPerformed(ActionEvent e) {

 

42

System.out.println("Cancel button clicked");

 

43

}

 

 

 

 

 

 

 

 

 

 

44

}

 

 

 

 

 

 

 

 

 

Two listener classes are defined in lines 34–44. Each listener class implements ActionListener to process ActionEvent. The object listener1 is an instance of OKListenerClass (line 18), which is registered with the button jbtOK (line 20). When the OK button is clicked, the actionPerformed(ActionEvent) method (line 36) in OKListenerClass is invoked to process the event. The object listener2 is an instance of CancelListenerClass (line 19), which is registered with the button jbtCancel in line 21. When the OK button is clicked, the

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]