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:
main
method)
Required Java files:
AverageTester.java
JustPlaneFun.java
Plane.java
Point.java
PointFun.java
PointPrinter.java
PointReader.java
SimpleInput.java
SimpleOutput.java
TextPlane.java
TextPlaneFun.java
Optional applet files:
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
.
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.
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.
main
method. In general, this design
is a good one to follow. One class will contain only the main
method. The other classes will do the actual work.
main
method creates a number of objects in different
contexts (not only a Plane
, but also Point
s).
plot
requires a Point
, we can create one on
the fly.
Plane
in order to use it successfully. All we need to know is that we can
add points with plot
.
In Experiment J2.2
you will consider how one uses the Point
and Plane
classes together, using the
JustPlaneFun
class to coordinate the two.
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:
public
, which indicates that the method is
generally accessible. (That is, any program that creates an appropriate
object can use this method of the object.)
void
.
SimpleOutput
object. (It also uses the
point to be printed, but that will be handled implicitly.) A method that
reads in a point will need a SimpleInput
object.
Each formal parameter is described with
(1) a type and (2) a name. Note that the formal parameter
gives a name to the parameter for use within the method. The names of the formal
and actual parameters do not need to match.
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.
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.
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.
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.
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.
One of the more confusing aspects of Java is the treatment of variables
that store references to objects. Objects, like
Point
s and String
s, 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.
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
paintBrush.drawOval(int left, int top, int width, int height)
paintBrush.drawRect(int left, int top, int width, int
height)
paintBrush.fillRect(int left, int top, int width, int height)
paintBrush.drawLine(int x1, int x2, int y1, int y2)
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.
Name: ________________
ID:_______________
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.
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).
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.
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?
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.
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.
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?
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.
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.
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
.
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.
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.
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.
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.
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.
Write a program, Smiley.java
that draws a smiley face by
plotting points appropriately.
Write a program, Initials.java
, that draws your initials by
plotting points appropriately.
Using the techniques from Experiment J2.8, draw your name in a rainbow of colors. (Your name will appear in each color.)
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.
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.
Experiment J2.1, Step 1.
You won't be able to execute Point
. Why not?
Because it doesn't include a main
method.
Point
s 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.
[Front Door] [Introduction] [Code]
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