Experiments in Java


Session J2: Objects and Methods

In this laboratory session, you will build and use your first Java objects and develop your first Java classes. The purposes of this lab session are to

Your instructor will tell you which of the proposed experiments you are to perform.

Prerequisite skills:

Required Java files:

Optional applet files:


Discussion

Objects

You may have heard that Java is an object-oriented language. What does that mean? Being an object-oriented language means that Java programs are collections of objects that communicate with each other. An object can be almost anything, from a number to a virtual person. Each object has certain attributes, such as the value of the number or the eye color of the virtual person. In addition, each object has certain abilities, which are provided by methods. For example, a number might be able to add itself to another number, a virtual person might be able to blink, and an electronic book might be able to tell you where to find information on a particular topic.

In Java, objects are grouped into classes. A class specifies the methods each object provides and the kinds and names of attributes each object in the class has. Objects differ in the particular values associated with attributes. In addition, objects with different values for their attributes will most likely work differently. For example, adding the number 2 is different than adding the number 3.

What does this mean in terms of the nitty-gritty details? In particular, how do you use objects when you are programming? As you've seen, Java programs are based on a main method. You can use this method to create objects and then tell them to do things (you ask them to execute methods). In fact, in the experiments you did in the previous lab you may have created SimpleInput and SimpleOutput objects. You then used the SimpleOutput objects to write output to the computer screen and the SimpleInput objects to read input from the keyboard. You've also used Java's built-in String objects.

What objects can you use other than these three objects? Java comes with thousands of built-in objects. More importantly, you can define your own objects. Today, you will use and extend an existing class, Point. You will also build your own very simple classes, PointPrinter and PointReader.

Creating objects

To use an object in Java, you must first create the object and make a variable refer to that object. For example, to create a new SimpleOutput object and have out refer to it, we use

SimpleOutput out = new SimpleOutput();

As this suggests, you need the new command to create objects. In addition, you need to construct the object you are creating. A constructor is a method used to create new objects that initializes the values of the object.

For example, suppose we had a class of objects representing dates, with corresponding year, month, and day. In order to create a new date, we'd need to specify the year, month, and day. Hence, the constructor would need three values. Here's an example in which we create the date April 1, 1998.

SimpleDate date = new SimpleDate(1998, 4, 1);

Note that the year, month, and day are given as values in parentheses following the name of the class. These are called the parameters to the constructor. (You may also see them referred to as arguments, actual parameters, or actuals.)

How did I know which order to use when building the object? I looked at the documentation. The person who designs a class determines the available constructors and the order in which parameters to constructors are supplied. The clients of a class must consult documentation to determine which constructors are available and how they should be used.

Similarly, if we were to create the point (2,3) in the plane, we might write

Point pt = new Point(2,3);

Note that we didn't need any parameters when creating a new SimpleOutput object. That's because the default for these objects is to print to the screen and they don't need any other information. There is also a no parameter constructor for Point that creates a point at (0,0).

What can you do with a point once you've created one? It's somewhat up to the designer. You might move it left, right, up, or down. You might ask for its value or its distance from the origin.

The following is a simple program that creates a point, moves it a little, and then prints out a little bit of information about it.


import Point;

/**
 * Build a point and move it around.
 *
 * @version 1.1 of September 1998
 * @author Samuel A. Rebelsky
 */
public class PointFun {
  /**
   * Build a point and move it around.
   */
  public static void main(String[] args) {
    // We'll be generating some output.
    SimpleOutput out = new SimpleOutput();
    // The point we'll be playing with.
    Point pt = new Point(2,3);
    // Print some basic information.
    out.println("(" + pt.getX() + "," + pt.getY() + ")");
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
    // Move it right a little bit.
    out.println("Shifting right by 0.7");
    pt.shiftRight(0.7);
    // Print current information.
    out.println("(" + pt.getX() + "," + pt.getY() + ")");
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
    // Move it up a little bit.
    out.println("Shifting up by 2.5");
    pt.shiftUp(2.5);
    // Print current information.
    out.println("(" + pt.getX() + "," + pt.getY() + ")");
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
    // Move it left a little bit.
    out.println("Shifting left by 10.2");
    pt.shiftLeft(10.2);
    // Print current information.
    out.println("(" + pt.getX() + "," + pt.getY() + ")");
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
  } // main(String[])
} // class PointFun


What should you observe about this? First, that whenever we need information from an object we need to request it by calling a method. Second, that the ability to get information does not tell us much about how the object is designed (we'll come back to this later). For example, is the distance of the point from the origin stored within the point or only computed on demand?

In Experiment J2.1 you will consider some issues in using and printing points.

Coordinating objects

While it is certainly useful to deal with points numerically, many times we want to see them plotted on the plane. If we were given a Plane class, how might we plot some points?

Build a new Plane object.
For each point,
  Build a new point.
  Plot it.

Here is a simple class which does just that.


import Plane;

/**
 * A simple attempt to play with the Plane and Point classes.
 *
 * @version 1.0 of May 1998
 * @author Samuel A. Rebelsky
 */
public class JustPlaneFun {
  /**
   * Build a plane and display it.
   */
  public static void main(String[] args) {
    // Build the plane.
    Plane plane = new Plane();
    // Plot a few points.
    plane.plot(new Point(1,3));
    plane.plot(new Point(-2.5,4));
    plane.plot(new Point(4,-5.2));
  } // main(String[])
} // class JustPlaneFun


You should observe a number of things about this class.

In Experiment J2.2 you will consider how one uses the Point and Plane classes together, using the JustPlaneFun class to coordinate the two.

Building your own methods

Note that in our experiments and programs above, we had a number of operations in common. In PointFun.java, we printed the point in the same way again and again and again. If we made a change in the way we decided to print points, we'd need to modify a great deal of code. It would be useful to write the instructions once and then simply say something like ``print out this point''.

Similarly, in the experiments we needed to write instructions for reading in a point in different programs (both in PointFun.java and JustPlaneFun.java). Here it would be useful to just write ``read in a point''.

Can we create such shorthands? Yes! We will make a copy of Point.java and develop methods that provide the shorthands.

What is involved in a method definition? Four things:

It is also helpful to begin each method with a short comment that describes what the method does.

We now have the tools to build a method that prints out a point and its distance from the origin. We will add this method to the Point class. What parameters will this method need? The SimpleOutput object that does the printing. Why is there no parameter for the point to print? Because Java's object-oriented design suggests that each point will provide this method, hence the point to print is implicit. (Just as we write pt.getX(), we'll write pt.print(out).)

The method header therefore begins

public void print(SimpleOutput out) {

What does the body of the method look like? More or less like the code we used elsewhere.

  out.println("(" + this.getX() + "," + this.getY() + ")");
  out.println("  distance from origin: " + 
              this.distanceFromOrigin());

The this refers to the current object. Since getX and getY must be called for a particular object, we need to specify that object. Since we want to print the current object, we use this.

As always, you must end the method with a right curly brace.

How do we use our new method? Just like the methods we've used in the past. We create the object and then call the method.

Point pt = new Point(2,3);
pt.print(out);
Point another = new Point(4,2);
another.print(out);

What should you observe about this new method? First, we've added a name to some common code and parameterized that common code, which means that we can use it even with points with different names.

In Experiment J2.3 you will add the new print method to the Point class.

Creating your own classes

What if you'd like to write print, but you do not have access to the source code for Point? (In commercial settings, you will rarely have access to the source code for the classes you use.) As you will see in a later session, you can extend existing classes. However, that is beyond this introductory session. For now, the best solution may be to create your own new class that knows how to print points. Whenever you want to print a point, you create an object in this class. Some programmers consider such helper classes an odd design tactic. However, at this point in your career you will find many benefits from using them.

How do we begin a new class? As in past experiments, begin with

public class PointPrinter {

In this case, the print method will need to take two parameters: not just the output object, but also the explicit point to print. The method will begin

public void print(SimpleOutput out, Point pt) {

What does the body of the method look like? More or less like the code we used elsewhere.

    out.println("(" + pt.getX() + "," + pt.getY() + ")");
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());

And, as always, we end our method with a right curly brace. Putting it all together and adding a few short comments, we get


import Point;
import SimpleOutput;

/**
 * Some utilities for printing points.
 */
public class PointPrinter {

  // +---------+--------------------------------------------------
  // | Methods |
  // +---------+

  /**
   * Print a point using a particular output object.
   */
  public void print(SimpleOutput out, Point pt) {
    out.println("(" + pt.getX() + "," + pt.getY() + ")");
    out.println("  distance from origin: " + 
                pt.distanceFromOrigin());
  } // print(SimpleOutput, Point)
} // class PointPrinter


How do we use our new class? We create a new object in the class and then call its method, as in

    PointPrinter printer = new PointPrinter();
    Point pt = new Point(2,3);
    printer.print(out,pt);
    Point another = new Point(4,2);
    printer.print(out,another);

What should you observe about this new class? First, we've once again added a name to some common code and parameterized that common code, which means that we can use it even with points with different names. Second, in order to use the new method, we need to create an object that provides that method. For now, this will be your model for programming in Java: when you need a new method, you'll need to put it in a class and create an object that provides the method, which fits in well with Java's object-oriented paradigm.

In Experiment J2.4 you will experiment with this newly-created class.

Return values

So far, all of the methods we've created have modified the object or printed output. At times, we want to write methods that return values. For example, we might want to write methods that give the x coordinate of a point or the distance of a point from the origin.

How do we write methods that return values? It turns out that it's not much different than writing methods that do not return values. First, you need to determine what type will be returned (e.g., integer, string, etc.). In the declaration for the method, you need to write that type, as in

  public type method(...) {
    ...
  } // method(...)

For example, we might declare getX as

  public int getX() {
    ...
  } // getX()

Next, we need to specify which value to return from the method. We do this with a return statement, as in

  public int getX() {
    return xcoordinate;
  } \\ getX()

Similarly, to return the average of two numbers, you might write

  /**
   * Compute the average of two doubles.
   */
  public double average(double a, double b) {
    double ave (a + b) / 2;
    return ave;
  } // average(double,double)

In Experiment J2.5 you will create a simple class that can compute averages.

Static methods

You may have found it awkward to need to create a new helper object (in this case PointPrinter) every time you needed a helper method (in this case, print). This may be especially true if you've worked in other languages in which it is possible to define methods separate from objects and classes.

If you are sure that you need an object-independent method, Java permits you to create so-called static methods (also called class methods). Such methods are associated with particular classes, but do not require the creation of objects to use them.

For example, let's suppose that we wanted to write a method that reads in x and y coordinates and returns a point. Here's a sketch of the body of that method.

    float x;  // The x coordinate  
    float y;  // The y coordinate
    out.print("Enter the x coordinate: ");
    x = in.readFloat();
    out.print("Enter the y coordinate: ");
    y = in.readFloat();
    return new Point(x,y);

We'll place this method in a class called PointReader. Now, suppose that we want to be able to use that method without creating a new PointReader. We can declare the method as static, as in

static public Point read(SimpleOutput out, SimpleInput in) {

If you place this method within PointReader, you can refer to it as PointReader.read. If you create an object, reader, of class PointReader, you can also refer to this method as helper.read.

Experience shows that static methods often lead to problems for beginning programmers. Hence, static methods will be used rarely, if at all, in subsequent exercises.

In Experiment J2.6 you will consider some issues pertaining to static methods.

Detour: The main method

By now, you may have realized that all of those main methods you've been creating are, in fact, static methods. As you might guess, Java's main is static so that you do not need to create a new object in order to run it. In fact, when you execute a class, you are actually telling the Java virtual machine to call the main method of that class.

Assigning objects

One of the more confusing aspects of Java is the treatment of variables that store references to objects. Objects, like Points and Strings, are treated differently than primitive values, like integers. In particular, when you assign integer variables, the value is copied from one to another. However, when you assign objects, a reference is copied. In effect, Java allows multiple variables to refer to the same object.

For example, consider the following code:

SimpleOutput out = new SimpleOutput();
int a;
int b;
a = 3;
b = a;
a = 2;
out.print("a = " + a);
out.print(", ");
out.println("b = " + b);
b = 10;
out.print("a = " + a);
out.print(", ");
out.println("b = " + b);

This code will print out

a = 2, b = 3
a = 2, b = 10

This suggests that the value stored in variable a is copied to variable b in the line

b = a

but that no relationship between the two is maintained.

As a contrast, consider the following code:

    SimpleOutput out = new SimpleOutput();
    Point p1 = new Point(2,3);
    Point p2 = p1;
    out.println("Originally");
    out.println("p1: (" + p1.getX() + "," + p1.getY() + ")");
    out.println("p2: (" + p2.getX() + "," + p2.getY() + ")");

    p1.shiftLeft(4);
    out.println("After shifting p1 left 4");   
    out.println("p1: (" + p1.getX() + "," + p1.getY() + ")");
    out.println("p2: (" + p2.getX() + "," + p2.getY() + ")");

    p2.shiftUp(3);
    out.println("After shifting p2 up 3");
    out.println("p1: (" + p1.getX() + "," + p1.getY() + ")");
    out.println("p2: (" + p2.getX() + "," + p2.getY() + ")");

This code will print out

Originally
p1: (2,3)
p2: (2,3)
After shifting p1 left 4
p1: (-2,3)
p2: (-2,3)
After shifting p2 up 3
p1: (-2,6)
p2: (-2,6)

In this case, both p1 and p2 refer to the same Point object. Hence, a change made to that object through p1 is reflected in p2 and vice-versa.

In many ways, this corresponds to our normal sense of objects. Each ``real world'' object has many names. For example, you might call your teacher ``Professor Smith'' and one of your fellow students might call your teacher ``Teach''. If you give ``Professor Smith'' an apple, then your fellow student will still be able to note that ``Teach'' has an apple.

But this association is not permanent. You are free to change which object a variable refer to. For example, consider the following code

    Point p1 = new Point(2,3);
    Point p2 = p1;
    out.println("(" + p1.getX() + "," + p1.getY() + ")");
    out.println("(" + p2.getX() + "," + p2.getY() + ")");
    p2 = new Point(1,1);
    out.println("(" + p1.getX() + "," + p1.getY() + ")");
    out.println("(" + p2.getX() + "," + p2.getY() + ")");

This code will print

(2,3)
(2,3)
(2,3)
(1,1)

This output happens because the assignment to p2 changed the reference and not the object. Again, this effect corresponds to our normal sense of naming. If you take computer science from Professor Smith and mathematics from Professor Jones, then you might use ``Teach'' to refer to Professor Smith during computer science and Professor Jones during mathematics. When you ask ``Teach'' a question, who you ask depends on who ``Teach'' currently refers to.

In Experiment J2.7 you will consider some issues relating to assigning objects.

Fonts and graphics for applets

This section is optional and is intended for classes emphasizing applets or pursuing a simultaneous discussion of applications and applets.

The applets you created in the first laboratory session were relatively primative. All they did was print a simple message, in some font that the applet viewer or Web browser selected. Obviously, you'd like more abilities and control. In particular, most programmers expect to be able to draw pictures in their applets and to select the color and typeface for text.

As you might expect, much of this control has to do with objects and methods. In particular, there is a Font class (more particularly, java.awt.Font) that lets you create new objects for controlling the appearance of text. In addition, objects in the java.awt.Graphics class provide a number of methods for drawing other objects.

When you want to write text in a new font, you must first create a new Font object (or reuse an existing Font object) that specifies basic details of the font: the logical name (SansSerif, Serif, Monospaced, etc.), the size (10pt, 12pt, etc.), and the style (plain, bold, italic, or bold-italic). The command to create a new Font is

  Font myFont = new Font(name, style, size)

where the style must be selected from Font.PLAIN, Font.BOLD, Font.ITALIC, or Font.BOLD+Font.ITALIC. For example,

    Font myFont = new Font("Serif", Font.BOLD, 24);

Once you have selected a font, you must tell the graphics object to use that font with setFont. For example, the following paint method paints the string ``Hello World'' in a 24-point, bold, serif font.

  public void paint(Graphics paintBrush) {
    Font myFont = new Font("Serif", Font.BOLD, 24);
    paintBrush.setFont(myFont);
    paintBrush.drawString("Hello World", 10, 40);
  } // paint(Graphics)

Note that you cannot specify color as part of a font selection. Color is determined by the graphics object that does the actual drawing. You tell the graphics object what color to use with the setColor method. What colors can you use? The basic set consists of: Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, and Color.yellow. For example, to draw the word ``Hello'' in green and ``Goodbye'' in red, I might write

    paintBrush.setColor(Color.green);
    paintBrush.drawString("Hello", 10, 30);
    paintBrush.setColor(Color.red);
    paintBrush.drawString("Goodbye", 15, 60);

What are all these Color.xxx things? They are predefined objects, specified within the library class java.awt.Color. Hence, in order to use any of these colors, you must import that class.

But these colors do not give you a very rich pallet. What if you want more colors? You can create your own colors. That is, you can create your own objects that are members of java.awt.Color and that give you more precise control than the basic colors. The easiest way to create a new color is by specifying red, green, and blue components (each a value between 0 and 255). For example,

   Color myPurple = new Color(...);

You are encouraged to experiment with these components to see how they are used to form different colors.

But what about drawing something other than pieces of text? Java's Graphics objects provide a number of methods to support drawing shapes, including

In Experiment J2.8, you will make use of Java's Font and Color classes. In Experiment J2.9, you will test the various drawing primitives.


Experiments

Name: ________________
ID:_______________

Experiment J2.1: Printing out a point

Required code files:

Step 1. Make a copy of Point.java. Compile it. Try to execute it. Record your results. Compare your notes with the notes at the end of this lab.


 
 
 

Step 2. Make a copy of PointFun.java. Compile and execute it and record the results. Do you observe anything odd? What do you think is going on? For an explanation, turn to the end of this lab.


 
 
 
 
 
 

Step 3. Update the main method of PointFun.java so that it shifts the point five spaces right, five spaces up, ten spaces left, five spaces down, and then five spaces right, printing the position and distance from the origin each time. Record your code.


 
 
 
 
 
 

Step 4. Run your code and record any observations.


 
 
 
 
 
 

Step 5. Update the main method of PointFun.java to read in the initial x and y coordinates. Record your solution.


 
 
 
 
 
 

Experiment J2.2: Coordinating classes

There are two versions of this experiment. Experiment J2.2A is designed for students working on computers that include graphics displays. Experiment J2.2B is designed for students working on computers that only support textual displays (or for other classes that do not wish to use graphics).

Experiment J2.2A: Coordinating classes (graphical application)

Required code files:

Step 1. Make copies of Point.java, Plane.java, and JustPlaneFun.java. Compile all three. Execute JustPlaneFun and record the results.


 
 
 

Step 2. Modify JustPlaneFun to use only one point that you move around. Start the point at (1,1) and shift the point right five, up five, left ten, down five, and right five, plotting it after each step. Execute the modified version and record the results. What do these results suggest?


 
 
 
 
 
 

Step 3. Modify JustPlaneFun to input the point to plot. Note that the point won't be plotted until after the main method terminates. Why? Because main just sets things in motion and Plane waits until main is done to display itself. Record your code.


 
 
 
 
 
 

Experiment J2.2B: Coordinating classes (textual application)

Required code files:

Step 1. Make copies of Point.java, TextPlane.java, and TextPlaneFun.java. Compile all three. Execute TextPlaneFun and summarize the output.


 
 
 

Step 2. Modify JustPlaneFun to use only one point that you move around. Start the point at (1,1) and shift the point right five, up five, left ten, down five, and right five, plotting it and displaying the plane after each step. Execute the modified version and record the results. What do these results suggest?


 
 
 
 
 
 

Step 3. Modify JustPlaneFun to input the point to plot. Record your code.


 
 
 
 
 
 

Step 4. Plot points at (0.5,0.5) and (1.2,2) and display the plane. Where does the point appear? What does that suggest?


 
 
 
 
 
 

Experiment J2.3: Your own method

Required code files:

Step 1. Modify Point so that it includes the new print method we developed earlier. Here is the code for that method.

  /**
   * Print information about the current point.
   */
  public void print(SimpleOutput out) {
    out.println("(" + this.getX() + "," + this.getY() + ")");
    out.println("  distance from origin: " + 
                this.distanceFromOrigin());
  } // print(SimpleOutput)

Step 2. Modify PointFun so that it uses the new print method to print the various points. Compile the various files and then execute PointFun. Summarize your changes to the program. Record the output from the program.


 
 
 
 
 
 

Step 3. Modify Point so that it prints out points as <X,Y> rather than (X,Y). Recompile just Point and then execute PointFun. Record the results.


 
 
 
 
 
 

Step 4. Change all instances of out to screen in the print method of Point. Recompile just Point and then execute PointFun. Record the results. What happened? Was that what you expected?


 
 
 
 
 
 

After you have written down your observations, you may wish to look at the notes on this problem.

Experiment J2.4: Your own class

Required code files:

Step 1. Modify PointFun so that it creates a PointPrinter object called printer and uses printer to print the various positions of the point. Compile the various files and then execute PointFun. Summarize your changes to the program. Record the output from the program.


 
 
 
 
 
 

Step 2. Modify PointPrinter so that it prints out points as <X,Y> rather than (X,Y). Recompile just PointPrinter and then execute PointFun. Record the results.


 
 
 
 
 
 

Step 3. Change all instances of pt to apoint in PointPrinter. Recompile just PointPrinter and then execute PointFun. Record the results. What happened? Was that what you expected?


 
 
 
 
 
 

You may wish to look at the notes on this problem.

Step 4. Change all instances of out to screen in PointPrinter. Recompile just PointPrinter and then execute PointFun. Record the results. What happened? Was that what you expected?


 
 
 
 
 
 

You may wish to look at the notes on this problem.

Experiment J2.5: Return values

Step 1. Create a new class, AverageComputer (stored in AverageComputer.java) with the following method.

  /**
   * Compute the average of two doubles.
   */
  public double average(double a, double b) {
    double ave = (a + b) / 2;
    return ave;
  } // average(double,double)

Step 2. Make a copy of AverageTester.java, which reads as follows.


import AverageComputer;
import SimpleInput;
import SimpleOutput;

/**
 * Some simple tests of the AverageComputer class.
 *
 * @author Samuel A. Rebelsky
 * @author Your Name Here
 * @version 1.0 of January 1999
 */
public class AverageTester {
  /**
   * Test away!
   */
  public static void main(String[] args) {
    // Prepare for reading input and printing output.
    SimpleOutput out = new SimpleOutput();
    SimpleInput in = new SimpleInput();
    // Build a new computer.
    AverageComputer computer = new AverageComputer();
    // The two values we'll be reading.
    double first;
    double second;

    // Read the two values.
    out.print("Enter a number: ");
    first = in.readDouble();
    out.print("Enter another number: ");
    second = in.readDouble();
    // Compute the average and print the result.
    out.println("The average of " + first + " and " + second + " is " +
                computer.average(first,second));
  } // main(String[])

} // AverageTester


Compile both AverageComputer and AverageTester. Execute AverageTester. Record the results.


 
 
 

Step 3. Change the average method of AverageComputer to read

  public double average(double a, double b) {
    double ave = (a + b) / 2;
  } // average(double,double)

What do you expect to happen when you try to recompile AverageComputer?


 
 
 

Step 4. Recompile AverageComputer and record the error messages you receive. What do the error messages suggest?


 
 
 
 
 
 

Step 5. Change the average method of AverageComputer to read

  public double average(double a, double b) {
    double ave = (a + b) / 2;
    return 0;
  } // average(double,double)

What do you expect to happen when you try to execute AverageTester with the modified AverageComputer?


 
 
 

Step 6. Recompile AverageComputer and execute AverageTester. Use 1 and 2 as the inputs. What is the output? What does this suggest?


 
 
 
 
 
 

Step 7. Change the average method of AverageComputer to read

  public double average(double a, double b) {
    double ave = (a + b) / 2;
    return 0;
    return ave;
  } // average(double,double)

Try to recompile AverageComputer and record the error messages. What do these messages suggest?


 
 
 
 
 
 

Experiment J2.6: Static methods

Required code files:

Step 1. Make a copy of PointReader.java, which is as defined as follows.


import SimpleInput;
import SimpleOutput;
import Point;

import SimpleOutput;
import SimpleInput;

/**
 * Simple methods for reading in points.  Arguably, these could also be
 * part of the Point class, but some issues have dictated that we use 
 * a separate class.
 * 
 * Developed as an illustration of static methods.
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of January 1999
 */
public class PointReader {
  // +----------------+------------------------------------------
  // | Static Methods |
  // +----------------+
  
  /**
   * Prompt for and read one point.
   */
  static public Point read(SimpleOutput out, SimpleInput in) {
    float x;  // The x coordinate
    float y;  // The y coordinate
    out.print("Enter the x coordinate: ");
    x = in.readFloat();
    out.print("Enter the y coordinate: ");
    y = in.readFloat();
    return new Point(x,y);
  } // read(SimpleOutput, SimpleInput)
} // class PointReader


Note that PointReader.java contains a PointReader class with only one method, a static read method. Compile PointReader.

Step 2. Add the following lines to the main method of PointFun.

    PointReader reader = new PointReader();
    PointPrinter printer = new PointPrinter();
    Point zebra = reader.read(out,in);
    printer.print(out,zebra);

If your copy of PointFun does not create a SimpleInput object called in, you should insert the following line before those lines.

   SimpleInput in = new SimpleInput();

What do you expect these lines to do?


 
 
 

Step 3. Recompile and execute PointFun. Record the new results. Were they what you expected? Explain the results.


 
 
 
 
 
 

Step 4. Add the following lines to the main method of PointFun.

    Point stripes = PointReader.read(out,in);
    printer.print(out,stripes);

Recompile and execute PointFun. Record the new results. Were they what you expected?


 
 
 
 
 
 

Step 5. Add the following lines to the main method of PointFun

    Point white = PointReader.read(out,in);
    PointPrinter.print(out,white);

Try to recompile and execute PointFun. What happens? What does this suggest?


 
 
 
 
 
 

After recording your answer, you may wish to look at the notes on this problem. You should also remove these lines from the program.

Step 6. Add the following lines to the main method of PointFun

    Point black = PointReader.read(in,out);
    printer.print(out,black);

Try to recompile and execute PointFun. What happens? What does this suggest?


 
 
 
 
 
 

After recording your answer, you may wish to look at the notes on this problem. You should also remove these lines from the program.

Experiment J2.7: Copying objects

Required code files:

Step 1. Write a class, PointExperiment, that imports the Point class and has an empty main method. Compile and execute the program. Your program should do nothing. You need not enter any results for this step.

Step 2. Add the following lines to the main method. Recompile and execute the program. Record the output. Is this what you expected? Why or why not?

    SimpleOutput out = new SimpleOutput();
    int a;
    int b;
    a = 3;
    b = 2*a;
    out.println("a = " + a + ", b = " + b);
    a = 1;
    out.println("a = " + a + ", b = " + b);


 
 
 
 
 
 

Step 3. Add the following lines to the main method. Recompile and execute the program. Record the output. Explain why the program generated that output.

    Point p1 = new Point(1,1);
    Point p2 = p1;
    out.println("(" + p1.getX() + "," + p1.getY() + ")");
    out.println("(" + p2.getX() + "," + p2.getY() + ")");
    p1.shiftLeft(1);
    out.println("(" + p1.getX() + "," + p1.getY() + ")");
    out.println("(" + p2.getX() + "," + p2.getY() + ")");
    p2.shiftDown(1);
    out.println("(" + p1.getX() + "," + p1.getY() + ")");
    out.println("(" + p2.getX() + "," + p2.getY() + ")");


 
 
 
 
 
 

Step 4. Add the following lines to the main method. Recompile and execute the program. Record the new output. Explain why the program generated that output. Explain why this output differs from that of the previous segment.

    Point p3 = new Point(1,1);
    Point p4 = new Point(1,1);
    out.println("(" + p3.getX() + "," + p3.getY() + ")");
    out.println("(" + p4.getX() + "," + p4.getY() + ")");
    p3.shiftLeft(1);
    out.println("(" + p3.getX() + "," + p3.getY() + ")");
    out.println("(" + p4.getX() + "," + p4.getY() + ")");
    p4.shiftDown(1);
    out.println("(" + p3.getX() + "," + p3.getY() + ")");
    out.println("(" + p4.getX() + "," + p4.getY() + ")");


 
 
 
 
 
 

Step 5. Consider the following code, which is missing some parts.

    Point p5 = new Point(0,0);
     ...
    Point p6 = __________________;
    out.println("Initially ...");
    out.println("  difference in X values is " + (p5.getX() - p6.getX()));
    out.println("  difference in Y values is " + (p5.getY() - p6.getY()));
    p6.shiftUp(1);
    out.println("After shifting p6 up 1 ...");
    out.println("  difference in X values is " + (p5.getX() - p6.getX()));
    out.println("  difference in Y values is " + (p5.getY() - p6.getY()));
    p5.shiftRight(3);
    out.println("After shifting p5 right 3 ...");
    out.println("  difference in X values is " + (p5.getX() - p6.getX()));
    out.println("  difference in Y values is " + (p5.getY() - p6.getY()));

What expression should be used in the blank so that the output is as follows?

Initially ...
  difference in X values is 0
  difference in Y values is 0
After shifting p6 up 1 ...
  difference in X values is 0
  difference in Y values is -1
After shifting p5 right 3 ...
  difference in X values is 3
  difference in Y values is -1

Your code should generate this output no matter how p5 changes in the section marked by ellipses.

Enter the expression assigned to p6 here.


 
 
 

Experiment J2.8: Changing the font

Optional applet experiment

Required files:

Before you begin, if you have not already done so, please familiarize yourself with the applet and HTML file. Make a copy of the two files. Read the code to make sure you understand the various parts. Compile HelloWorldApplet.java. Load the applet, using whatever technique your instructor specifies. (You might load it in a browser like Netscape Navigator or Microsoft Internet Explorer; you might run an application like Sun's appletviewer.)

Step 1. Add the following lines to the top of HelloWorldApplet.java.

import java.awt.Font;
import java.awt.Color;

Why do you think you were asked to add those lines?


 
 
 

After recording your answer, you may wish to consult the notes on this step.

Step 2. Replace the paint method of HelloWorldApplet with the following.

  public void paint(Graphics paintBrush) {
    Font myFont = new Font("Serif", 24, Font.BOLD);
    paintBrush.setFont(myFont);
    paintBrush.drawString("Hello World", 10, 30);
  } // paint(Graphics)

Recompile HelloWorldApplet and load the applet from helloworld.html. Record the result.


 
 
 

Step 3. Remove the line that reads

import java.awt.Color;

What do you expect will happen when you try to recompile HelloWorldApplet and load the applet from helloworld.html?


 
 
 

Confirm your answer by recompiling and loading the applet. You may also wish to consult the notes on this step.

Reinsert the line that you just deleted.

Step 4. Remove the line that reads

import java.awt.Font;

What do you expect will happen when you try to recompile HelloWorldApplet and load the applet from helloworld.html?


 
 
 

Confirm your answer by recompiling and loading the applet. You may also wish to consult the notes on this step.

Reinsert the line that you just deleted.

Step 5. What changes would you have to make for the message to be printed in 14pt sans serif italic?


 
 
 
 
 
 

Confirm your answer by making those changes to HelloWorldApplet, recompiling, and loading the applet with helloworld.html.

Step 6. Replace the paint method of HelloWorldApplet with the following

  public void paint(Graphics paintBrush) {
    paintBrush.setFont(new Font("Serif", 18, Font.ITALIC));
    paintBrush.drawString("Hello World", 10, 30);
  } // paint(Graphics)

Recompile HelloWorldApplet and load the applet from helloworld.html. What does this result suggest?

Warning! This is a conceptually difficult problem.


 
 
 
 
 
 

After entering your answer, you may wish to consult the notes on this step.

Step 8. Add the following line to the beginning of the paint method of HelloWorldApplet (before the call to setFont).

    paintBrush.setColor(Color.red);

What effect do you expect this change to have?


 
 
 

Confirm your answer by compiling HelloWorldApplet and loading the applet from helloworld.html.

Step 9. Move the setColor line to the end of the paint method of HelloWorldApplet (after the call to drawString). The body of this method should now read

    paintBrush.setFont(new Font("Serif", 18, Font.ITALIC));
    paintBrush.drawString("Hello World", 10, 30);
    paintBrush.setColor(Color.red);

What effect do expect this change to have?


 
 
 

Confirm your answer by compiling HelloWorldApplet and loading the applet from helloworld.html. You may also wish to consult the note on this step.

Step 10. Add the following line to the start of the paint method.

    paintBrush.setColor(new Color(255, 0, 255));

What effect do you expect this change to have?


 
 
 

Confirm your answer by compiling HelloWorldApplet and loading the applet from helloworld.html.

Step 11. Update the paint method to read

    paintBrush.setFont(new Font("Serif", Font.PLAIN, 24));
    paintBrush.setColor(Color.red);
    paintBrush.drawString("Hello world", 10, 30);
    paintBrush.setColor(Color.blue);
    paintBrush.drawString("Hello world", 12, 32);

What do you expect the new applet to show?


 
 
 

Confirm your answer by compiling HelloWorldApplet and loading the applet from helloworld.html.

Step 12. Update the paint method to read

    paintBrush.setFont(new Font("Serif", Font.PLAIN, 24));
    paintBrush.setColor(Color.blue);
    paintBrush.drawString("Hello world", 12, 32);
    paintBrush.setColor(Color.red);
    paintBrush.drawString("Hello world", 10, 30);

How will this applet differ from the one in the previous step?


 
 
 

Confirm your answer by compiling HelloWorldApplet and loading the applet from helloworld.html.

Experiment J2.9: Some simple pictures

Optional applet experiment

Required files:

Step 1. Make copies of CircleApplet.java and circle.html. Read both files. What do you expect the applet to do?


 
 
 

Step 2. Compile CircleApplet. Load the applet using circle.html. Note what you see.


 
 
 

Step 3. Indicate what you expect to happen if you change the line that reads

    paintBrush.fillOval(0,0,40,40);

to instead read

    paintBrush.fillOval(0,0,50,30);


 
 
 

Confirm your answer by compiling CircleApplet and loading the applet from circle.html.

Step 4. Change that line to read

    paintBrush.drawOval(0,0,50,30);

What effect do you expect this change to have?


 
 
 

Confirm your answer by compiling CircleApplet and loading the applet from circle.html.

Step 5. Change that line to read

    paintBrush.fillRect(10,0,50,30);

What effect do you expect this change to have?


 
 
 

Confirm your answer by compiling CircleApplet and loading the applet from circle.html.

Step 7. Change that line to read

    paintBrush.fillOval(10,-25,50,50);

What effect do you expect this change to have?


 
 
 

Confirm your answer by compiling CircleApplet and loading the applet from circle.html.

Step 8. Modify CircleApplet so that it draws a red circle of radius 25 centered at (30,30). Enter your code here.


 
 
 

Step 9. Modify CircleApplet so that it draws both the red circle and a blue circle of radius 10 centered at (30,30). Enter the new code here.


 
 
 

Step 10. What happens if the paint method draws the blue circle before drawing the red circle?


 
 
 

Step 11. Draw a series of five concentric circles centered at (50,50), using a different color for each circle. Enter your code here.


 
 
 
 
 
 


Post-Laboratory Problems

Problem J2-A: Shifting points

Add a shiftAndPrint method to PointPrinter that moves a point right 3, up 3, left 6, down 6, right six, up 3, and left 3, printing the result at each step.

Problem J2-B: Shifting points, revisited

Add a shiftAndPlot method to PointPrinter that moves a point right 3, up 3, left 6, down 6, right six, up 3, and left 3, plotting the result at each step. Write a program that reads in the point and uses the helper to plot the point at each position.

Problem J2-C: Drawing a grid

Write a program, Grid.java, that prints out a 3 by 3 grid of points on the plane. Make the spacing in the grid one unit.

Problem J2-D: Drawing a grid, revisited

Write a program, Grid.java, that prints out a 3 by 3 grid of points on the plane. Input the spacing in the grid and the center point in the grid.

Problem J2-E: Happiness

Write a program, Smiley.java that draws a smiley face by plotting points appropriately.

Problem J2-F: Initials

Write a program, Initials.java, that draws your initials by plotting points appropriately.

Problem J2-G: Rainbow Text

Using the techniques from Experiment J2.8, draw your name in a rainbow of colors. (Your name will appear in each color.)

Problem J2-H: Other Drawing Methods

In this session, you learned about six methods provided by java.awt.Graphics for drawing basic shapes: drawString, drawLine, drawRect, drawOval, fillRect, and fillOval. Are these all that's available? Consult the Java documentation and write short summaries of the other drawing methods.

Problem J2-I: Determining Text Width

Instead of the rainbow-drawing technique from Problem J2-G, you might want to draw each letter in a different color. However, this makes it necessary for you not only to change the color before drawing each letter, but also to determine the correct place to draw each letter. Does Java give you the tools for doing so? Yes. There is a FontMetrics class that helps you determine the width of strings. Read the documentation on that class and write instructions that a classmate could use to write his or her name with each letter in a different color.


Notes

Experiment J2.1, Step 1. You won't be able to execute Point. Why not? Because it doesn't include a main method. Points can be used to manipulate points on the plane, but they won't work by themselves; they need to be coordinated by a separate main routine.

Experiment J2.1, Step 2. Why are the numbers so strange? Because Java, like many programming languages, tends to approximate numbers. However, the internal working of the computer lead to different approximations than we normally get. So, when we subtract 10.2 from 2.7, we should get -7.5. However, the approximation leads to the strange number you see.

Experiment J2.3, Step 4. Experiment J2.4, Step 3. Experiment J2.4, Step 4. All of these cases show that the name used within a method is independent of the name used outside the method. In effect, Java renames any arguments used in a method call so that they correspond to the parameter names in the method. As long as you are consistent within the method, you should be fine.

Experiment J2.6, Step 5. If you call a nonstatic method (a normal method) and don't provide an accompanying object, the Java compiler will issue an error message. In this case, print is not a static method, but it's being used as if it were a static method.

Experiment J2.6, Step 6. The parameters are being passed to the method in the wrong order. The read method is designed to take a SimpleOutput object as its first parameter and a SimpleInput object as its second parameter.

Experiment J2.8, Step 1. It's likely we'll be creating new Font objects and new Color objects, so we import those two classes.

Experiment J2.8, Step 3. We have yet to make explicit use of a Color, so there is no immediate harm in removing the line. However, since we expect to use colors in the near future, it behooves us to reinsert the line once we are done testing.

Experiment J2.8, Step 4. Because we use the Font class and do not import that class, Java is likely to complain that the class has been used without a corresponding import statement.

Experiment J2.8, Step 6. In effect, the one line

    paintBrush.setFont(new Font("Serif", Font.ITALIC, 18));

replaces the two lines

    Font myFont = new Font("Serif", Font.ITALIC, 18));
    paintBrush.setFont(myFont);

That is, it creates a new Font object and then immediately passes it to setFont, rather than storing it in a variable and then passing it with that variable.

If you are only creating a new Font to use with setFont, you can use this technique to avoid the intermediate step and the otherwise-unused variable. You'll find that many experienced Java programmers use similar shortcuts.

Experiment J2.8, Step 9. Since the paint color is only changed after the text has been drawn, there is no visible effect.


Copyright (c) 1998 Samuel A. Rebelsky. All rights reserved.

Source text last modified Wed Oct 6 12:40:45 1999.

This page generated on Tue Oct 26 15:39:58 1999 by Siteweaver.

Contact our webmaster at rebelsky@math.grin.edu