Solutions Manual: Chapter 9 Big Java, by Cay Horstmann 1

Review Exercises

R9.1

The following requires a cast:
c = i; // 1
i = j; // 3

R9.3

These assignments are legal:

Edible e = sub; // 1
sub = (Sandwich)e; // 5

R9.5

R9.7

The call Rectangle r = s.getBounds(); is an example of polymorphism because the Shape interface declares the method, the Rectangle class supports an implementation, and that implementation is picked at runtime.

R9.9

In the first implementation, you first need to create a DataSet object. To find the average salary, you would first need to add the Measureable objects and then construct another Measurable object to get the highest salary. You also need to modify the Employee class so that it implements the Measurable interface.

In the second implementation, you first construct a Measurer object to carry out the measurement, and then a DataSet object that takes in this measurement. An object value, instead of a Measureable object, is used to add all the object values. This is used to obtain the average and highest salary.

The second implementation is easier because the responsibility of measuring does not lie on the added objects. This way, you can define measurers to take on any kind of measurement.

R9.11

import java.awt.Rectangle;

/**

This program demonstrates the use

of a Measurer.

*/

public class DataSetTest

{

public static void main(String[] args)

{

Measurer m = new RectangleMeasurer();

DataSet data = new DataSet(m);

data.add(new Rectangle(5, 10, 20, 30));

data.add(new Rectangle(10, 20, 30, 40));

data.add(new Rectangle(20, 30, 5, 10));

System.out.println(

"Average area = " + data.getAverage());

Rectangle max = (Rectangle)data.getMaximum();

System.out.println("Maximum area = " + max);

}

}

import java.awt.Rectangle;

public class RectangleMeasurer implements Measurer

{

public double measure(Object anObject)

{

Rectangle aRectangle = (Rectangle)anObject;

double area = aRectangle.getWidth() * aRectangle.getHeight();

return area;

}

}

R9.13

A strategy object is an object that carries out a particular strategy for a computation. An useful strategy for the DataSet class can be a Filter object that filters about certain information before being passed to the DataSet object.

R9.15

No, but the addActionListener can be called multiple times.

R9.17

The compiler gives an error saying that the local variable is accessed from within inner class and needs to be declared final.

Programming Exercises

P9.1

Measurable.java

/**

Describes any class whose objects can be measured.

*/

public interface Measurable

{

/**

Computes the measure of the object.

@return the measure

*/

double getMeasure();

}

DataSet.java

/**

Computes the average of a set of data values.

*/

public class DataSet

{

/**

Constructs an empty data set.

*/

public DataSet()

{

sum = 0;

count = 0;

maximum = null;

}

/**

Adds a data value to the data set

@param x a data value

*/

public void add(Measurable x)

{

sum = sum + x.getMeasure();

if (count == 0 || maximum.getMeasure() < x.getMeasure())

maximum = x;

count++;

}

/**

Gets the average of the added data.

@return the average or 0 if no data has been added

*/

public double getAverage()

{

if (count == 0) return 0;

else return sum / count;

}

/**

Gets the largest of the added data.

@return the maximum or 0 if no data has been added

*/

public Measurable getMaximum()

{

return maximum;

}

private double sum;

private Measurable maximum;

private int count;

}

Die.java

import java.util.Random;

/**

This class models a die that, when cast, lands on a random

face.

*/

public class Die implements Measurable

{

/**

Constructs a die with a given number of sides

@param s the number of sides, e.g. 6 for a normal die

*/

public Die(int s)

{

sides = s;

generator = new Random();

castNumber = 0;

}

/**

Simulates a throw of the die

@return the face of the die

*/

public int cast()

{

castNumber = 1 + generator.nextInt(sides);

return castNumber;

}

/**

Gets the cast number of the current die

@return the current cast number

*/

public double getMeasure()

{

return castNumber;

}

private Random generator;

private int sides;

private int castNumber;

}

DieTest.java

/**

This program simulates casting a die ten times

and prints out its average.

*/

public class DieTest

{

public static void main(String[] args)

{

final int TRIES = 10;

DataSet ds = new DataSet();

Die d = new Die(6);

for (int i = 1; i <= TRIES; i++)

{

int n = d.cast();

ds.add(d);

System.out.print(n + " ");

}

System.out.println();

System.out.println("The average is " + ds.getAverage());

}

}

P9.3

Measurer.java

/**

Describes any class whose objects can measure other objects.

*/

public interface Measurer

{

/**

Computes the measure of an object.

@param anObject the object to be measured

@return the measure

*/

double measure(Object anObject);

}

DataSet.java

/**

Computes the average of a set of data values.

*/

public class DataSet

{

/**

Constructs an empty data set with a given measurer

@param aMeasurer the measurer that is used to measure data values

*/

public DataSet(Measurer aMeasurer)

{

sum = 0;

count = 0;

maximum = null;

measurer = aMeasurer;

}

/**

Adds a data value to the data set

@param x a data value

*/

public void add(Object x)

{

sum = sum + measurer.measure(x);

if (count == 0

|| measurer.measure(maximum) < measurer.measure(x))

maximum = x;

count++;

}

/**

Gets the average of the added data.

@return the average or 0 if no data has been added

*/

public double getAverage()

{

if (count == 0) return 0;

else return sum / count;

}

/**

Gets the largest of the added data.

@return the maximum or 0 if no data has been added

*/

public Object getMaximum()

{

return maximum;

}

private double sum;

private Object maximum;

private int count;

private Measurer measurer;

}

Person.java

/**

This class represents a person's name and height

*/

public class Person

{

/**

Constructs a Person object

@param aName the name of the person

@param aHeight the height of the person

*/

public Person(String aName, double aHeight)

{

name = aName;

height = aHeight;

}

/**

Gets the name of the person

@return name the person's name

*/

public String getName()

{

return name;

}

/**

Gets the height of the person

@return height the person's height

*/

public double getHeight()

{

return height;

}

private String name;

private double height;

}

ExP9_3.java

/**

This program demonstrates the use of the interface Measurer

*/

public class ExP9_3

{

public static void main(String[] args)

{

class PersonMeasurer implements Measurer

{

public double measure(Object anObject)

{

Person aPerson = (Person)anObject;

return aPerson.getHeight();

}

}

Measurer m = new PersonMeasurer();

DataSet data = new DataSet(m);

data.add(new Person("Joe", 183));

data.add(new Person("Chrissy", 158));

data.add(new Person("Bobby", 175));

System.out.println("Average height = " + data.getAverage());

Person p = (Person)data.getMaximum();

String name = p.getName();

System.out.println("The tallest person is " + name);

}

}

P9.5

Measurer.java

/**

Describes any class whose objects can measure other objects.

*/

public interface Measurer

{

/**

Computes the measure of an object.

@param anObject the object to be measured

@return the measure

*/

double measure(Object anObject);

}

DataSet.java

/**

Computes the average of a set of data values.

*/

public class DataSet

{

/**

Constructs an empty data set with a given measurer

@param aMeasurer the measurer that is used to measure data values

*/

public DataSet(Measurer aMeasurer)

{

sum = 0;

count = 0;

minimum = null;

measurer = aMeasurer;

}

/**

Adds a data value to the data set

@param x a data value

*/

public void add(Object x)

{

sum = sum + measurer.measure(x);

if (count == 0

|| measurer.measure(minimum) > measurer.measure(x))

minimum = x;

if (count == 0

|| measurer.measure(minimum) < measurer.measure(x))

maximum = x;

count++;

}

/**

Gets the average of the added data.

@return the average or 0 if no data has been added

*/

public double getAverage()

{

if (count == 0) return 0;

else return sum / count;

}

/**

Gets the largest of the added data.

@return the maximum or 0 if no data has been added

*/

public Object getMaximum()

{

return maximum;

}

/**

Gets the smallest of the added data.

@return the minimum or 0 if no data has been added

*/

public Object getMinimum()

{

return minimum;

}

private double sum;

private Object minimum;

private Object maximum;

private int count;

private Measurer measurer;

}

DataSetTest.java

import java.awt.Rectangle;

/**

This program demonstrates the use of a Measurer.

*/

public class DataSetTest

{

public static void main(String[] args)

{

class RectangleMeasurer implements Measurer

{

public double measure(Object anObject)

{

Rectangle aRectangle = (Rectangle)anObject;

double area

= aRectangle.getWidth() * aRectangle.getHeight();

return area;

}

}

Measurer m = new RectangleMeasurer();

DataSet data = new DataSet(m);

data.add(new Rectangle(5, 10, 20, 30));

data.add(new Rectangle(10, 20, 30, 40));

data.add(new Rectangle(20, 30, 5, 10));

System.out.println("Average area = " + data.getAverage());

Rectangle max = (Rectangle)data.getMaximum();

Rectangle min = (Rectangle)data.getMinimum();

System.out.println("Maximum area = " + max);

System.out.println("Minimum area = " + min);

}

}

P9.7

Measurable.java

/**

Describes any class whose objects can be measured.

*/

public interface Measurable

{

/**

Computes the measure of the object.

@return the measure

*/

double getMeasure();

}

Measurer.java

/**

Describes any class whose objects can measure other objects.

*/

public interface Measurer

{

/**

Computes the measure of an object.

@param anObject the object to be measured

@return the measure

*/

double measure(Object anObject);

}

BankAccount.java

/**

A bank account has a balance that can be changed by

deposits and withdrawals.

*/

public class BankAccount implements Measurable

{

/**

Constructs a bank account with a zero balance

*/

public BankAccount()

{

balance = 0;

}

/**

Constructs a bank account with a given balance

@param initialBalance the initial balance

*/

public BankAccount(double initialBalance)

{

balance = initialBalance;

}

/**

Deposits money into the bank account.

@param amount the amount to deposit

*/

public void deposit(double amount)

{

double newBalance = balance + amount;

balance = newBalance;

}

/**

Withdraws money from the bank account.

@param amount the amount to withdraw

*/

public void withdraw(double amount)

{

double newBalance = balance - amount;

balance = newBalance;

}

/**

Gets the current balance of the bank account.

@return the current balance

*/

public double getBalance()

{

return balance;

}

public double getMeasure()

{

return balance;

}

private double balance;

}

DataSet.java

/**

Computes the average of a set of data values.

*/

public class DataSet

{

/**

Constructs an empty data set with a given measurer

@param aMeasurer the measurer that is used to measure data values

*/

public DataSet(Measurer aMeasurer)

{

sum = 0;

count = 0;

maximum = null;

measurer = aMeasurer;

}

/**

Adds a data value to the data set

@param x a data value

*/

public void add(Object x)

{

sum = sum + measurer.measure(x);

if (count == 0

|| measurer.measure(maximum) < measurer.measure(x))

maximum = x;

count++;

}

/**

Gets the average of the added data.

@return the average or 0 if no data has been added

*/

public double getAverage()

{

if (count == 0) return 0;

else return sum / count;

}

/**

Gets the largest of the added data.

@return the maximum or 0 if no data has been added

*/

public Object getMaximum()

{

return maximum;

}

private double sum;

private Object maximum;

private int count;

private Measurer measurer;

}

DataSetTest.java

import java.awt.Rectangle;

/**

This program demonstrates the use of a Measurer.

*/

public class DataSetTest

{

public static void main(String[] args)

{

class AccountMeasurer implements Measurer

{

public double measure(Object anObject)

{

BankAccount acct = (BankAccount)anObject;

return acct.getBalance();

}

}

class DefaultMeasurer implements Measurer

{

public double measure(Object o)

{

Measurable m = (Measurable)o;

return m.getMeasure();

}

}

Measurer m = new AccountMeasurer();

DataSet data = new DataSet(m);

data.add(new BankAccount(100));

data.add(new BankAccount(1000));

data.add(new BankAccount(10000));

System.out.println("Average balance = "

+ data.getAverage());

BankAccount b = (BankAccount)data.getMaximum();

double balance = b.getBalance();

System.out.println("Highest balance = " + balance);

Measurer measurer = new DefaultMeasurer();

DataSet d = new DataSet(measurer);

d.add(new BankAccount(200));

d.add(new BankAccount(2000));

d.add(new BankAccount(20000));

System.out.println("Average balance = "

+ d.getAverage());

Measurable max = (Measurable)d.getMaximum();

System.out.println("Highest balance = "

+ max.getMeasure());

}

}

P9.9

Drawable.java

import java.awt.Graphics2D;

/** Describes any class whose objects can draw other objects. */

public interface Drawable

{

void draw(Graphics2D g2);

}

Car.java

import java.awt.Graphics2D;

import java.awt.geom.Ellipse2D;

import java.awt.geom.Line2D;

import java.awt.geom.Point2D;

import java.awt.geom.Rectangle2D;

/**

A car shape that can be positioned anywhere on the screen.

*/

public class Car implements Drawable

{

/**

Constructs a car with a given top left corner

@param x the x coordinate of the top left corner

@param y the y coordinate of the top left corner

*/

public Car(double x, double y)

{

xLeft = x;

yTop = y;

}

/**

Draws the car

@param g2 the graphics context

*/

public void draw(Graphics2D g2)

{

Rectangle2D.Double body

= new Rectangle2D.Double(xLeft, yTop + 10, 60, 10);

Ellipse2D.Double frontTire

= new Ellipse2D.Double(xLeft + 10, yTop + 20, 10, 10);

Ellipse2D.Double rearTire

= new Ellipse2D.Double(xLeft + 40, yTop + 20, 10, 10);

// the bottom of the front windshield

Point2D.Double r1

= new Point2D.Double(xLeft + 10, yTop + 10);

// the front of the roof

Point2D.Double r2

= new Point2D.Double(xLeft + 20, yTop);

// the rear of the roof

Point2D.Double r3

= new Point2D.Double(xLeft + 40, yTop);

// the bottom of the rear windshield

Point2D.Double r4

= new Point2D.Double(xLeft + 50, yTop + 10);

Line2D.Double frontWindshield

= new Line2D.Double(r1, r2);

Line2D.Double roofTop

= new Line2D.Double(r2, r3);

Line2D.Double rearWindshield

= new Line2D.Double(r3, r4);

g2.draw(body);

g2.draw(frontTire);

g2.draw(rearTire);

g2.draw(frontWindshield);

g2.draw(roofTop);

g2.draw(rearWindshield);

}

private double xLeft;

private double yTop;

}

House.java

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.geom.Rectangle2D;

import java.awt.geom.Ellipse2D;

import java.awt.geom.Line2D;

import java.awt.geom.Point2D;

/**

This class draws a house by allowing the user to specify houses of different sizes

*/

public class House implements Drawable

{

/**

Constructor to initiate the bottom left corner, the width, and the height

@param x the left corner coordinate

@param y the bottom corner coordinate

*/

public House(int x, int y)

{

xleft = x;

ybottom = y;

}

/**

Draws the house

@param g2 the graphics context

*/

public void draw(Graphics2D g2)

{

final int WIDTH = 50;

final int HEIGHT = 75;

Rectangle2D.Double front =

new Rectangle2D.Double(xleft, ybottom - WIDTH, WIDTH, WIDTH);

Rectangle2D.Double door =

new Rectangle2D.Double(xleft + WIDTH / 5, ybottom - WIDTH / 2, WIDTH / 5, WIDTH / 2);

Rectangle2D.Double window =

new Rectangle2D.Double(xleft + WIDTH * 3 / 5, ybottom - WIDTH / 2, WIDTH / 5, WIDTH / 5);

Line2D.Double roofLeft =

new Line2D.Double(xleft, ybottom - WIDTH, xleft + WIDTH / 2, ybottom - HEIGHT);

Line2D.Double roofRight =

new Line2D.Double(xleft + WIDTH, ybottom - WIDTH, xleft + WIDTH / 2, ybottom - HEIGHT);

g2.draw(front);

g2.draw(door);

g2.draw(window);

g2.draw(roofLeft);

g2.draw(roofRight);

}

private int xleft;

private int ybottom;

}

ExP9_9.java

import java.applet.Applet;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.util.Random;

/**

This program demonstrates the use of a Drawable.

*/

public class ExP9_9 extends Applet

{

public ExP9_9()

{

generator = new Random();

}

public void paint(Graphics g)

{

Graphics2D g2 = (Graphics2D)g;

for (int i = 1; i <= 10; i++)

randomDrawable().draw(g2);

}

public Drawable randomDrawable()

{

Drawable d = null;

int x = generator.nextInt(getWidth());

int y = generator.nextInt(getHeight());

if (generator.nextBoolean())

d = new Car(x, y);

else

d = new House(x, y);

return d;

}

private Random generator;

}

P9.11

TimerTest.java

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JOptionPane;

import javax.swing.Timer;

import java.util.Date;

/**

This program tests the Timer class

and display the current time once every second.

*/

public class TimerTest

{

public static void main(String[] args)

{

class CurrentTime implements ActionListener

{

public void actionPerformed(ActionEvent event)

{

Date now = new Date();

System.out.println(now);

}

}

CurrentTime listener = new CurrentTime();

final int DELAY = 1000; // milliseconds between timer ticks

Timer t = new Timer(DELAY, listener);

t.start();

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

System.exit(0);

}

}

P9.13

Car.java

import java.awt.Graphics2D;

import java.awt.geom.Ellipse2D;

import java.awt.geom.Line2D;

import java.awt.geom.Point2D;

import java.awt.geom.Rectangle2D;

/**

A car shape that can be positioned anywhere on the screen.

*/

public class Car

{

/**

Constructs a car with a given top left corner

@param x the x coordinate of the top left corner

@param y the y coordinate of the top left corner

*/

public Car(double x, double y)

{

xLeft = x;

yTop = y;

}

/**

Draws the car

@param g2 the graphics context

*/

public void draw(Graphics2D g2)

{

Rectangle2D.Double body

= new Rectangle2D.Double(xLeft, yTop + 10, 60, 10);

Ellipse2D.Double frontTire

= new Ellipse2D.Double(xLeft + 10, yTop + 20, 10, 10);

Ellipse2D.Double rearTire

= new Ellipse2D.Double(xLeft + 40, yTop + 20, 10, 10);

// the bottom of the front windshield

Point2D.Double r1

= new Point2D.Double(xLeft + 10, yTop + 10);

// the front of the roof

Point2D.Double r2

= new Point2D.Double(xLeft + 20, yTop);

// the rear of the roof

Point2D.Double r3

= new Point2D.Double(xLeft + 40, yTop);

// the bottom of the rear windshield

Point2D.Double r4

= new Point2D.Double(xLeft + 50, yTop + 10);

Line2D.Double frontWindshield

= new Line2D.Double(r1, r2);

Line2D.Double roofTop

= new Line2D.Double(r2, r3);

Line2D.Double rearWindshield

= new Line2D.Double(r3, r4);

g2.draw(body);

g2.draw(frontTire);

g2.draw(rearTire);

g2.draw(frontWindshield);

g2.draw(roofTop);

g2.draw(rearWindshield);

}

private double xLeft;

private double yTop;

}

ExP9_13.java

import java.applet.Applet;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.Timer;

import javax.swing.JOptionPane;

/**

This program demonstrates the use of the Timer class

*/

public class ExP9_13 extends Applet

{

public ExP9_13()

{

x = 100;

y = 100;

c = new Car(x, y);

class CarMover implements ActionListener

{

public void actionPerformed(ActionEvent event)

{

c = new Car(x, y);

x++;

repaint();

}

}

CarMover listener = new CarMover();

final int DELAY = 100; // milliseconds between timer ticks

Timer t = new Timer(DELAY, listener);

t.start();

}

public void paint(Graphics g)

{

final Graphics2D g2 = (Graphics2D)g;

c.draw(g2);

}

private Car c;