Chapter 2. Using Objects

CHAPTER GOALS

  • To learn about variables

  • To understand the concepts of classes and objects

  • To be able to call methods

  • To learn about parameters and return values

  • To be able to browse the API documentation

    T To implement test programs

  • To understand the difference between objects and object references

    G To write programs that display simple shapes

Most useful programs don't just manipulate numbers and strings. Instead, they deal with data items that are more complex and that more closely represent1 entities in the real world. Examples of these data items include bank accounts, employee records, and graphical shapes.

The Java language is ideally suited for designing and manipulating such data items, or objects. In Java, you implement classes that describe the behavior of these objects. In this chapter, you will learn how to manipulate objects that belong to classes that have already been implemented. This knowledge will prepare you for the next chapter in which you will learn how to implement your own classes.

Types

Before we start with the main topic of this chapter, we need to go over some basic programming terminology. In the first three sections of this chapter, you will learn about the concepts of types, variables, and assignment.

A computer program processes values: numbers, strings, and more complex data items. In Java, every value has a type. For example, the number 13 has the type int (an abbreviation for "integer"), "Hello, World" has the type String, and the object System.out has the type PrintStream. The type tells you what operations you can carry out with the values. For example, you can compute the sum or product of any two integers. You can call println on any object of type PrintStream.

Note

A type specifies a set of values and the operations that can be carried out with the values.

Java has separate types for integers and floating-point numbers. Integers are whole numbers; floating-point numbers can have fractional parts. For example, 13 is an integer and 1.3 is a floating-point number.

The name "floating-point" describes the representation of the number in the computer as a sequence of the significant digits and an indication of the position of the decimal point. For example, the numbers 13000.0, 1.3, 0.00013 all have the same decimal digits: 13. When a floating-point number is multiplied or divided by 10, only the position of the decimal point changes; it "floats". This representation is related to the "scientific" notation 1.3 × 10−4. (Actually, the computer represents numbers in base 2, not base 10, but the principle is the same.)

If you need to process numbers with a fractional part, you should use the type called double, which stands for "double precision floating-point number". Think of a number in double format as any number that can appear in the display panel of a calculator, such as 1.3 or −0.333333333.

Note

The double type denotes floating-point numbers that can have fractional parts.

Table 2.1. Number Literals in Java

Number

Type

Comment

6

int

An integer has no fractional part.

−6

int

Integers can be negative.

0

int

Zero is an integer.

0.5

double

A number with a fractional part has type double.

1.0

double

An integer with a fractional part .0 has type double.

1E6

double

A number in exponential notation: 1 × 106 or 1000000. Numbers in exponential notation always have type double.

2.96E-2

double

Negative exponent: 2.96 × 10−2 = 2.96 / 100 = 0.0296

Number Literals in Java
 

Error: Do not use a comma as a decimal separator.

Number Literals in Java
 

Error: Do not use fractions; use decimal notation: 3.5.

When a value such as 13 or 1.3 occurs in a Java program, it is called a number literal. Do not use commas when you write number literals in Java. For example, 13,000 must be written as 13000. To write numbers in exponential notation in Java, use the notation En instead of "×10n". For example, 1.3×10–4 is written as 1.3E-4. Table 1 shows how to write integer and floating-point literals in Java.

You may wonder why Java has separate integer and floating-point number types. Pocket calculators don't need a separate integer type; they use floating-point numbers for all calculations. However, integers have several advantages over floating-point numbers. They take less storage space, are processed faster, and don't cause rounding errors. You will want to use the int type for quantities that can never have fractional parts, such as the length of a string. Use the double type for quantities that can have fractional parts, such as a grade point average.

There are several other number types in Java that are not as commonly used. We will discuss these types in Chapter 4. For most programs in this book, however, the int and double types are all you need for processing numbers.

Note

In Java, the number types are primitive types, and numbers are not objects.

In Java, the number types (int, double, and the less commonly used types) are primitive types. Numbers are not objects. The number types have no methods.

However, you can combine numbers with operators such as + and -, as in 10 + n or n - 1. To multiply two numbers, use the * operator. For example, 10 × n is written as 10 * n.

A combination of variables, literals, operators, and/or methods (which you will see in Section 2.4) is called an expression. A typical example of an expression is

x + y * 2

As in mathematics, the * operator binds more strongly than the + operator. That is, x + y * 2 means the sum of x and y * 2. If you want to multiply the sum of x and y by 2, use parentheses:

(x + y) * 2

Note

Numbers can be combined by arithmetic operators such as +, -, and *.

Number Literals in Java

2. Which number type would you use for storing the area of a circle?

3. Why is the expression 13.println() an error?

4. Write an expression to compute the average of the values x and y.

Variables

You often want to store values so that you can use them at a later time. To remember a value, you need to hold it in a variable. A variable is a storage location in the computer's memory that has a type, name, and contents. For example, here we declare three variables:

String greeting = "Hello, World!";
PrintStream printer = System.out;
int width = 20;

Note

You use variables to store values that you want to use at a later time. A variable has a type, a name, and a value.

The first variable is called greeting. It can be used to store String values, and it is set to the value "Hello, World!". The second variable, printer, stores a PrintStream value, and the third stores an integer.

Variables can be used in place of the values that they store:

printer.println(greeting); // Same as System.out.println("Hello, World!")
printer.println(width); // Same as System.out.println(20)

When you declare your own variables, you need to make two decisions.

  • What type should you use for the variable?

  • What name should you give the variable?

The type depends on the intended use. If you need to store a string, use the String type for your variable. If you need a number, choose the int or double type.

It is an error to store a value whose type does not match the type of the variable. For example, the following is an error:

String greeting = 20; // ERROR: Types don't match

Table 2.2. Variable Declarations in Java

Variable Name

Comment

int width = 10;

Declares an integer variable and initializes it with 10.

int area = width * height;

The initial value can depend on other variables. (Of course, width and height must have been previously declared.)

Variable Declarations in Java

Error: The type is missing. This statement is not a declaration but an assignment of a new value to an existing variable—see Section 2.3.

Variable Declarations in Java

Error: You cannot initialize a number with a string.

int width, height;

Declares two integer variables in a single statement. In this book, we will declare each variable in a separate statement.

You cannot use a String variable to store an integer. The compiler checks type mismatches to protect you from errors.

When deciding on a name for a variable, you should make a choice that describes the purpose of the variable. For example, the variable name greeting is a better choice than the name g.

Note

Identifiers for variables, methods, and classes are composed of letters, digits, and the underscore character.

An identifier is the name of a variable, method, or class. Java imposes the following rules for identifiers:

  • Identifiers can be made up of letters, digits, and the underscore (_) and dollar sign ($) characters. They cannot start with a digit, though.

  • You cannot use spaces or symbols such as ? or %.

  • Furthermore, you cannot use reserved words, such as public, as names; these words are reserved exclusively for their special Java meanings. (See Appendix C for all reserved words in Java.)

These are firm rules of the Java language. If you violate one of them, the compiler will report an error. Moreover, there are a couple of conventions that you should follow so that other programmers will find your programs easy to read:

  • Variable and method names should start with a lowercase letter. It is OK to use an occasional uppercase letter, such as farewellMessage. This mixture of lowercase and uppercase letters is sometimes called "camel case" because the uppercase letters stick out like the humps of a camel.

  • Class names should start with an uppercase letter. For example, Greeting would be an appropriate name for a class, but not for a variable.

  • You should not use the $ symbol in names. It is intended for names that are automatically generated by tools.

Note

By convention, variable names should start with a lowercase letter.

If you violate these conventions, the compiler won't complain, but you will confuse other programmers who read your code.

Table 2.3. Variable Names in Java

Variable Name

Comment

farewellMessage

Use "camel case" for variable names consisting of multiple words.

x

In mathematics, you use short variable names such as x or y. This is legal in Java, but not very common, because it can make programs harder to understand.

Variable Names in Java

Caution: Variable names are case-sensitive. This variable name is different from greeting.

Variable Names in Java

Error: Variable names cannot start with a number.

Variable Names in Java

Error: Variable names cannot contain spaces.

Variable Names in Java

Error: You cannot use a reserved word as a variable name.

Table 3 shows examples of legal and illegal variable names in Java.

Variable Names in Java
Greeting1
g
void
101dalmatians
Hello, World
<greeting>

6. Declare a variable to hold your name. Use camel case in the variable name.

The Assignment Operator

You can change the value of a variable with the assignment operator (=). For example, consider the variable declaration

int width = 10; 
The Assignment Operator

Use the assignment operator (=) to change the value of a variable.

If you want to change the value of the variable, simply assign the new value:

width = 20; 
The Assignment Operator

The assignment replaces the original value of the variable (see Figure 1).

Assigning a New Value to a Variable

Figure 2.1. Assigning a New Value to a Variable

It is an error to use a variable that has never had a value assigned to it. For example, the following assignment statement has an error:

int height;
width = height;   // ERROR—uninitialized variable height

The compiler will complain about an "uninitialized variable" when you use a variable that has never been assigned a value. (See Figure 2.)

An Uninitialized Variable

Figure 2.2. An Uninitialized Variable

Executing the Statement width = width + 10

Figure 2.3. Executing the Statement width = width + 10

The remedy is to assign a value to the variable before you use it:

int height = 30;
width = height; // OK

Note

All variables must be initialized before you access them.

Or, even better, initialize the variable when you declare it.

int height = 30;
int width = height; // OK

The right-hand side of the = symbol can be a mathematical expression. For example,

width = height + 10;

This means "compute the value of height + 10 and store that value in the variable width".

In the Java programming language, the = operator denotes an action, to replace the value of a variable. This usage differs from the mathematical usage of the = symbol, as a statement about equality. For example, in Java, the following statement is entirely legal:

width = width + 10;

This means "compute the value of width + 10

Executing the Statement width = width + 10

In Java, it is not a problem that the variable width is used on both sides of the = symbol. Of course, in mathematics, the equation width = width + 10 has no solution.

Executing the Statement width = width + 10

8. How do you change the value of the greeting variable to "Hello, Nina!"?

Objects, Classes, and Methods

We now come to the main purpose of this chapter: a closer understanding of objects. An object is a value that you can manipulate by calling one or more of its methods. A method consists of a sequence of instructions that can access the internal data of an object. When you call the method, you do not know exactly what those instructions are, or even how the object is organized internally. However, the behavior of the method is well-defined, and that is what matters to us when we use it.

Note

Objects are entities in your program that you manipulate by calling methods.

For example, you saw in Chapter 1 that System.out refers to an object. You manipulate it by calling the println method. When the println method is called, some activities occur inside the object, and the ultimate effect is that text appears in the console window. You don't know how that happens, and that's OK. What matters is that the method carries out the work that you requested.

Note

A method is a sequence of instructions that accesses the data of an object.

Figure 4 shows a representation of the System.out object. The internal data is symbolized by a sequence of zeroes and ones. Think of each method (symbolized by the gears) as a piece of machinery that carries out its assigned task.

In Chapter 1, you encountered two objects:

  • System.out

  • "Hello, World!"

The type of an object is a class. The System.out object belongs to the class Print-Stream. The "Hello, World!" object belongs to the class String. A class specifies the methods that you can apply to its objects.

You can use the println method with any object that belongs to the PrintStream class. System.out is one such object. It is possible to obtain other objects of the Print-Stream class. For example, you can construct a PrintStream object to send output to a file. However, we won't discuss files until Chapter 11.

Note

A class declares the methods that you can apply to its objects.

Just as the PrintStream class provides methods such as println and print for its objects, the String class provides methods that you can apply to String objects. One of them is the length method. The length method counts the number of characters in a string. You can apply that method to any object of type String. For example, the sequence of statements

Representation of the System.out Object

Figure 2.4. Representation of the System.out Object

A Representation of Two String Objects

Figure 2.5. A Representation of Two String Objects

String greeting = "Hello, World!";
int n = greeting.length();

sets n to the number of characters in the String object "Hello, World!". After the instructions in the length method are executed, n is set to 13. (The quotation marks are not part of the string, and the length method does not count them.)

The length method—unlike the println method—requires no input inside the parentheses. However, the length method yields an output, namely the character count.

In the next section, you will see in greater detail how to supply method inputs and obtain method outputs.

Let us look at another method of the String class. When you apply the toUpperCase method to a String object, the method creates another String object that contains the characters of the original string, with lowercase letters converted to uppercase. For example, the sequence of statements

String river = "Mississippi";
String bigRiver = river.toUpperCase();

sets bigRiver to the String object "MISSISSIPPI".

When you apply a method to an object, you must make sure that the method is declared in the appropriate class. For example, it is an error to call

System.out.length(); // This method call is an error

The PrintStream class (to which System.out belongs) has no length method.

Let us summarize. In Java, every object belongs to a class. The class declares the methods for the objects. For example, the String class declares the length and toUpper-Case methods (as well as other methods—you will learn about most of them in Chapter 4). The methods form the public interface of the class, telling you what you can do with the objects of the class. A class also declares a private implementation, describing the data inside its objects and the instructions for its methods. Those details are hidden from the programmers who use objects and call methods.

Note

The public interface of a class specifies what you can do with its objects. The hidden implementation describes how these actions are carried out.

Figure 5 shows two objects of the String class. Each object stores its own data (drawn as boxes that contain characters). Both objects support the same set of methods—the interface that is specified by the String class.

Occasionally, a class declares two methods with the same name and different parameter types. For example, the PrintStream class declares a second method, also called println, as

public void println(int output)

That method is used to print an integer value. We say that the println name is overloaded because it refers to more than one method.

A Representation of Two String Objects

10. How can you print out the uppercase version of "Hello, World!"?

11. Is it legal to call river.println()? Why or why not?

Method Parameters and Return Values

Methods are fundamental building blocks of Java programs. A program performs useful work by calling methods. In this section, we will examine how to provide inputs into a method, and how to obtain the result of the method.

Most methods require inputs that give details about the work that the method needs to do. For example, the println method has an input: the string that should be printed. Computer scientists use the technical term parameter for method inputs. We say that the string greeting is a parameter of the method call

System.out.println(greeting);

Note

A parameter is an input to a method.

Figure 6 illustrates passing of the parameter to the method.

Technically speaking, the greeting parameter is an explicit parameter of the println method. The object on which you invoke the method is also considered a parameter of the method call; it is called the implicit parameter. For example, System.out is the implicit parameter of the method call

System.out.println(greeting);

Note

The implicit parameter of a method call is the object on which the method is invoked. All other parameters are explicit parameters.

Some methods require multiple explicit parameters, others don't require any explicit parameters at all. An example of the latter is the length method of the String class (see Figure 7). All the information that the length method requires to do its job—namely, the character sequence of the string—is stored in the implicit parameter object.

Passing a Parameter to the println Method

Figure 2.6. Passing a Parameter to the println Method

Invoking the length Method on a String Object

Figure 2.7. Invoking the length Method on a String Object

The length method differs from the println method in another way: it has an output. We say that the method returns a value, namely the number of characters in the string. You can store the return value in a variable:

int n = greeting.length();

Note

The return value of a method is a result that the method has computed for use by the code that called it.

You can also use the return value as a parameter of another method:

System.out.println(greeting.length());

The method call greeting.length() returns a value—the integer 13. The return value becomes a parameter of the println method. Figure 8 shows the process.

Not all methods return values. One example is the println method. The println method interacts with the operating system, causing characters to appear in a window. But it does not return a value to the code that calls it.

Let us analyze a more complex method call. Here, we will call the replace method of the String class. The replace method carries out a search-and-replace operation, similar to that of a word processor. For example, the call

river.replace("issipp", "our")

constructs a new string that is obtained by replacing all occurrences of "issipp" in "Mississippi" with "our". (In this situation, there was only one replacement.) The method returns the String object "Missouri". You can save that string in a variable:

river = river.replace("issipp", "our");

Or you can pass it to another method:

System.out.println(river.replace("issipp", "our"));
Passing the Result of a Method Call to Another Method

Figure 2.8. Passing the Result of a Method Call to Another Method

Calling the replace Method

Figure 2.9. Calling the replace Method

As Figure 9 shows, this method call has

  • one implicit parameter: the string "Mississippi"

  • two explicit parameters: the strings "issipp" and "our"

  • a return value: the string "Missouri"

When a method is declared in a class, the declaration specifies the types of the explicit parameters and the return value. For example, the String class declares the length method as

public int length()

That is, there are no explicit parameters, and the return value has the type int. (For now, all the methods that we consider will be "public" methods—see Chapter 10 for more restricted methods.)

The type of the implicit parameter is the class that declares the method—String in our case. It is not mentioned in the method declaration—hence the term "implicit".

The replace method is declared as

public String replace(String target, String replacement)

To call the replace method, you supply two explicit parameters, target and replacement, which both have type String. The returned value is another string.

When a method returns no value, the return type is declared with the reserved word void. For example, the PrintStream class declares the println method as

public void println(String output)
Calling the replace Method

13. What is the result of the call river.replace("p", "s")?

14. What is the result of the call greeting.replace("World", "Dave").length()?

15. How is the toUpperCase method declared in the String class?

Constructing Objects

Most Java programs need to work on a variety of objects. In this section, you will see how to construct new objects. This allows you to go beyond String objects and the System.out object.

To learn about object construction, let us turn to another class: the Rectangle class in the Java class library. Objects of type Rectangle describe rectangular shapes—see Figure 10. These objects are useful for a variety of purposes. You can assemble rectangles into bar charts, and you can program simple games by moving rectangles inside a window.

Note that a Rectangle object isn't a rectangular shape—it's an object that contains a set of numbers. The numbers describe the rectangle (see Figure 11). Each rectangle is described by the x- and y-coordinates of its top-left corner, its width, and its height.

It is very important that you understand this distinction. In the computer, a Rectangle object is a block of memory that holds four numbers, for example x = 5, y = 10, width = 20, height = 30. In the imagination of the programmer who uses a Rectangle object, the object describes a geometric figure.

To make a new rectangle, you need to specify the x, y, width, and height values. Then invoke the new operator, specifying the name of the class and the parameters that are required for constructing a new object. For example, you can make a new rectangle with its top-left corner at (5, 10), width 20, and height 30 as follows:

new Rectangle(5, 10, 20, 30)

Note

Use the new operator, followed by a class name and parameters, to construct new objects.

Here is what happens in detail:

  1. The new operator makes a Rectangle object.

  2. It uses the parameters (in this case, 5, 10, 20, and 30) to initialize the data of the object.

  3. It returns the object.

Rectangular Shapes

Figure 2.10. Rectangular Shapes

Rectangle Objects

Figure 2.11. Rectangle Objects

The process of creating a new object is called construction. The four values 5, 10, 20, and 30 are called the construction parameters.

The new expression yields an object, and you need to store the object if you want to use it later. Usually you assign the output of the new operator to a variable. For example,

Rectangle box = new Rectangle(5, 10, 20, 30);

Some classes let you construct objects in multiple ways. For example, you can also obtain a Rectangle object by supplying no construction parameters at all (but you must still supply the parentheses):

new Rectangle()

This expression constructs a (rather useless) rectangle with its top-left corner at the origin (0, 0), width 0, and height 0.

Object Construction

17. The getWidth method returns the width of a Rectangle object. What does the following statement print?

System.out.println(new Rectangle().getWidth());

Accessor and Mutator Methods

In this section we introduce a useful terminology for the methods of a class. A method that accesses an object and returns some information about it, without changing the object, is called an accessor method. In contrast, a method whose purpose is to modify the internal data of an object is called a mutator method.

Note

An accessor method does not change the internal data of its implicit parameter. A mutator method changes the data.

For example, the length method of the String class is an accessor method. It returns information about a string, namely its length. But it doesn't modify the string at all when counting the characters.

The Rectangle class has a number of accessor methods. The getX, getY, getWidth, and getHeight methods return the x- and y-coordinates of the top-left corner, the width, and the height values. For example,

double width = box.getWidth();

Now let us consider a mutator method. Programs that manipulate rectangles frequently need to move them around, for example, to display animations. The Rectangle class has a method for that purpose, called translate. (Mathematicians use the term "translation" for a rigid motion of the plane.) This method moves a rectangle by a certain distance in the x- and y-directions. The method call,

box.translate(15, 25);

moves the rectangle by 15 units in the x-direction and 25 units in the y-direction (see Figure 12). Moving a rectangle doesn't change its width or height, but it changes the top-left corner. Afterward, the rectangle that had its top-left corner at (5, 10) now has it at (20, 35).

This method is a mutator because it modifies the implicit parameter object.

Using the translate Method to Move a Rectangle

Figure 2.12. Using the translate Method to Move a Rectangle

Using the translate Method to Move a Rectangle

19. Which call to translate is needed to move the rectangle declared by Rectangle box = new Rectangle(5, 10, 20, 30) so that its top-left corner is the origin (0, 0)?

The API Documentation

The classes and methods of the Java library are listed in the API documentation. The API is the "application programming interface". A programmer who uses the Java classes to put together a computer program (or application) is an application programmer. That's you. In contrast, the programmers who designed and implemented the library classes such as PrintStream and Rectangle are system programmers.

You can find the API documentation on the Web. Point your web browser to http://java.sun.com/javase/7/docs/api/index.html. Appendix D contains an abbreviated version of the API documentation that may be easier to use at first. It is fine if you rely on the abbreviated documentation for your first programs, but you should eventually move on to the real thing.

Note

The API (Application Programming Interface) documentation lists the classes and methods of the Java library.

The API documentation documents all classes in the Java library—there are thousands of them (see Figure 13). Most of the classes are rather specialized, and only a few are of interest to the beginning programmer.

Locate the Rectangle link in the left pane, preferably by using the search function of your browser. Click on the link, and the right pane shows all the features of the Rectangle class (see Figure 14).

The API Documentation of the Standard Java Library

Figure 2.13. The API Documentation of the Standard Java Library

The API Documentation for the Rectangle Class

Figure 2.14. The API Documentation for the Rectangle Class

The Method Summary for the Rectangle Class

Figure 2.15. The Method Summary for the Rectangle Class

The API Documentation of the translate Method

Figure 2.16. The API Documentation of the translate Method

The API documentation for each class starts out with a section that describes the purpose of the class. Then come summary tables for the constructors and methods (see Figure 15). Click on the link of a method to get a detailed description (see Figure 16).

The detailed description of a method shows

  • The action that the method carries out.

  • The parameters that the method receives.

  • The value that it returns (or the reserved word void if the method doesn't return any value).

As you can see, the Rectangle class has quite a few methods. While occasionally intimidating for the beginning programmer, this is a strength of the standard library. If you ever need to do a computation involving rectangles, chances are that there is a method that does all the work for you.

For example, suppose you want to change the width or height of a rectangle. If you browse through the API documentation, you will find a setSize method with the description "Sets the size of this Rectangle to the specified width and height." The method has two parameters, described as

  • width - the new width for this Rectangle

  • height - the new height for this Rectangle

Now let us use this information to change the box object so that it is a square of side length 40. The name of the method is setSize, and we supply two parameters: the new width and height:

box.setSize(40, 40);

The API documentation contains another important piece of information about each class. The classes in the standard library are organized into packages. A package is a collection of classes with a related purpose. The Rectangle class belongs to the package java.awt (where awt is an abbreviation for "Abstract Windowing Tool-kit"), which contains many classes for drawing windows and graphical shapes. You can see the package name java.awt in Figure 14, just above the class name.

To use the Rectangle class from the java.awt package, you must import the package. Simply place the following line at the top of your program:

import java.awt.Rectangle;

Why don't you have to import the System and String classes? Because the System and String classes are in the java.lang package, and all classes from this package are automatically imported, so you never need to import them yourself.

Note

Java classes are grouped into packages. Use the import statement to use classes that are declared in other packages.

Importing a Class from a Package

21. In the API documentation of the String class, look at the description of the trim method. What is the result of applying trim to the string " Hello, Space ! "? (Note the spaces in the string.)

22. The Random class is declared in the java.util package. What do you need to do in order to use that class in your program?

Implementing a Test Program

In this section, we discuss the steps that are necessary to implement a test program. The purpose of a test program is to verify that one or more methods have been implemented correctly. A test program calls methods and checks that they return the expected results. Writing test programs is a very important skill.

In this section, we will develop a simple program that tests a method in the Rectangle class. The program performs the following steps:

  1. Provide a tester class.

  2. Supply a main method.

  3. Inside the main method, construct one or more objects.

  4. Apply methods to the objects.

  5. Display the results of the method calls.

  6. Display the values that you expect to get.

Our sample test program tests the behavior of the translate method. Here are the key steps (which have been placed inside the main method of the MoveTester class).

Rectangle box = new Rectangle(5, 10, 20, 30);

// Move the rectangle
box.translate(15, 25);

// Print information about the moved rectangle
System.out.print("x: ");
System.out.println(box.getX());
System.out.println("Expected: 20");

Note

A test program verifies that methods behave as expected.

We print the value that is returned by the getX method, and then we print a message that describes the value we expect to see.

This is a very important step. You want to spend some time thinking about the expected result before you run a test program. This thought process will help you understand how your program should behave, and it can help you track down errors at an early stage. Finding and fixing errors early is a very effective strategy that can save you a great deal of time.

Note

Determining the expected result in advance is an important part of testing.

In our case, the rectangle has been constructed with the top-left corner at (5, 10). The x-direction is moved by 15, so we expect an x-value of 5 + 15 = 20 after the move.

Here is a complete program that tests the moving of a rectangle.

ch02/rectangle/MoveTester.java

1    import java.awt.Rectangle;
2
3    public class MoveTester
4    {
5       public static void main(String[] args)
6       {
7          Rectangle box = new Rectangle(5, 10, 20, 30);
8
9          // Move the rectangle
10          box.translate(15, 25);
11
12          // Print information about the moved rectangle
13          System.out.print("x: ");
14          System.out.println(box.getX());
15          System.out.println("Expected: 20");
16
17          System.out.print("y: ");
18          System.out.println(box.getY());
19          System.out.println("Expected: 35");
20       }
21    }

Program Run

x: 20
Expected: 20
y: 35
Expected: 35
Implementing a Test Program

24. Why doesn't the MoveTester program need to print the width and height of the rectangle?

Object References

In Java, a variable whose type is a class does not actually hold an object. It merely holds the memory location of an object. The object itself is stored elsewhere—see Figure 17.

There is a reason for this behavior. Objects can be very large. It is more efficient to store only the memory location instead of the entire object.

We use the technical term object reference to denote the memory location of an object. When a variable contains the memory location of an object, we say that it refers to an object. For example, after the statement

Rectangle box = new Rectangle(5, 10, 20, 30);

Note

An object reference describes the location of an object.

the variable box refers to the Rectangle object that the new operator constructed. Technically speaking, the new operator returned a reference to the new object, and that reference is stored in the box variable.

It is very important that you remember that the box variable does not contain the object. It refers to the object. Two object variables can refer to the same object:

Rectangle box2 = box;
An Object Variable Containing an Object Reference

Figure 2.17. An Object Variable Containing an Object Reference

Two Object Variables Referring to the Same Object

Figure 2.18. Two Object Variables Referring to the Same Object

Now you can access the same Rectangle object both as box and as box2, as shown in Figure 18.

However, number variables actually store numbers. When you declare

int luckyNumber = 13;

then the luckyNumber variable holds the number 13, not a reference to the number (see Figure 19). The reason is again efficiency. Because numbers require little storage, it is more efficient to store them directly in a variable.

Note

Multiple object variables can contain references to the same object.

A Number Variable Stores a Number

Figure 2.19. A Number Variable Stores a Number

You can see the difference between number variables and object variables when you make a copy of a variable. When you copy a number, the original and the copy of the number are independent values. But when you copy an object reference, both the original and the copy are references to the same object.

Note

Number variables store numbers. Object variables store references.

Consider the following code, which copies a number and then changes the copy (see Figure 20):

int luckyNumber = 13: 
A Number Variable Stores a Number
int luckyNumber2 = luckyNumber;
A Number Variable Stores a Number
luckyNumber2 = 12;
A Number Variable Stores a Number

Now the variable luckyNumber contains the value 13, and luckyNumber2 contains 12.

Copying Numbers

Figure 2.20. Copying Numbers

Copying Object References

Figure 2.21. Copying Object References

Now consider the seemingly analogous code with Rectangle objects (see Figure 21).

Rectangle box = new Rectangle(5, 10, 20, 30); 
Copying Object References
Rectangle box2 = box;
Copying Object References
box2.translate(15, 25);
Copying Object References

Since box and box2 refer to the same rectangle after step

Copying Object References

You need not worry too much about the difference between objects and object references. Much of the time, you will have the correct intuition when you think of "the object box" rather than the technically more accurate "the object reference stored in box". The difference between objects and object references only becomes apparent when you have multiple variables that refer to the same object.

Copying Object References

26. After calling greeting2.toUpperCase(), what are the contents of greeting and greeting2?

Graphical Applications and Frame Windows

This is the first of several optional sections that teach you how to write graphical applications: applications that display drawings inside a window. Graphical applications look more attractive than the console applications that show plain text in a console window.

A graphical application shows information inside a frame: a window with a title bar, as shown in Figure 22. In this section, you will learn how to display a frame. In Section 3.9, you will learn how to create a drawing inside the frame.

Note

To show a frame, construct a JFrame object, set its size, and make it visible.

A Frame Window

Figure 2.22. A Frame Window

To show a frame, carry out the following steps:

  1. Construct an object of the JFrame class:

    JFrame frame = new JFrame();
  2. Set the size of the frame:

    frame.setSize(300, 400);

    This frame will be 300 pixels wide and 400 pixels tall. If you omit this step the frame will be 0 by 0 pixels, and you won't be able to see it. (Pixels are the tiny dots from which digital images are composed.)

  3. If you'd like, set the title of the frame:

    frame.setTitle("An Empty Frame");

    If you omit this step, the title bar is simply left blank.

  4. Set the "default close operation":

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    When the user closes the frame, the program automatically exits. Don't omit this step. If you do, the program continues running even after the frame is closed.

  5. Make the frame visible:

    frame.setVisible(true);

The simple program below shows all of these steps. It produces the empty frame shown in Figure 22.

The JFrame class is a part of the javax.swing package. Swing is the nickname for the graphical user interface library in Java. The "x" in javax denotes the fact that Swing started out as a Java extension before it was added to the standard library.

We will go into much greater detail about Swing programming in Chapters 3, 9, 10, and 18. For now, consider this program to be the essential plumbing that is required to show a frame.

ch02/emptyframe/EmptyFrameViewer.java

1  import javax.swing.JFrame;
2
3  public class EmptyFrameViewer
4  {
5     public static void main(String[] args)
6      {
7        JFrame frame = new JFrame();
8
9        frame.setSize(300, 400);
10        frame.setTitle("An Empty Frame");
11        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
12
13        frame.setVisible(true);
14      }
15  }
A Frame Window

28. How can a program display two frames at once?

Drawing on a Component

This section continues the optional graphics track. You will learn how to make shapes appear inside a frame window. The first drawing will be exceedingly modest: just two rectangles (see Figure 23). You'll soon see how to produce more interesting drawings. The purpose of this example is to show you the basic outline of a program that creates a drawing. You cannot draw directly onto a frame. Whenever you want to show anything inside a frame, be it a button or a drawing, you have to construct a component object and add it to the frame. In the Swing toolkit, the JComponent class represents a blank component.

Since we don't want to add a blank component, we have to modify the JComponent class and specify how the component should be painted. The solution is to declare a new class that extends the JComponent class. You will learn about the process of extending classes in Chapter 10. For now, simply use the following code as a template.

Note

In order to display a drawing in a frame, declare a class that extends the JComponent class.

public class RectangleComponent extends JComponent
{
   public void paintComponent(Graphics g)
   {
      Drawing instructions
   }
}

The extends reserved word indicates that our component class, RectangleComponent, can be used like a JComponent. However, the RectangleComponent class will be different from the plain JComponent class in one respect: Its paintComponent method will contain instructions to draw the rectangles.

Note

Place drawing instructions inside the paintComponent method. That method is called whenever the component needs to be repainted.

When the component is shown for the first time, the paintComponent method is called automatically. The method is also called when the window is resized, or when it is shown again after it was hidden.

The paintComponent method receives an object of type Graphics. The Graphics object stores the graphics state—the current color, font, and so on, that are used for drawing operations. However, the Graphics class is primitive. When programmers clamored for a more object-oriented approach for drawing graphics, the designers of Java created the Graphics2D class, which extends the Graphics class. Whenever the Swing toolkit calls the paintComponent method, it actually passes a parameter of type Graphics2D. Because we want to use the more sophisticated methods to draw two-dimensional graphics objects, we need to use the Graphics2D class. This is accomplished by using a cast:

Drawing Rectangles

Figure 2.23. Drawing Rectangles

public class RectangleComponent extends JComponent
{
   public void paintComponent(Graphics g)
   {
      // Recover Graphics2D
      Graphics2D g2 = (Graphics2D) g;
      ...
   }
}

Note

Use a cast to recover the Graphics2D object from the Graphics parameter of the paintComponent method.

We cover the concepts of extending classes and of casting in Chapter 10. For now, you should simply include the cast at the top of your paintComponent methods.

Now you are ready to draw shapes. The draw method of the Graphics2D class can draw shapes, such as rectangles, ellipses, line segments, polygons, and arcs. Here we draw a rectangle:

public class RectangleComponent extends JComponent
{
   public void paintComponent(Graphics g)
   {
       ...
      Rectangle box = new Rectangle(5, 10, 20, 30);
      g2.draw(box);
       ...
   }
}

Following is the source code for the RectangleComponent class. Note that the paintComponent method of the RectangleComponent class draws two rectangles.

As you can see from the import statements, the Graphics and Graphics2D classes are part of the java.awt package.

ch02/rectangles/RectangleComponent.java

1  import java.awt.Graphics;
2  import java.awt.Graphics2D;
3  import java.awt.Rectangle;
4  import javax.swing.JComponent;
5
6  /*
7     A component that draws two rectangles.
8  */
9  public class RectangleComponent extends JComponent
10 {
11    public void paintComponent(Graphics g)
12    {
13       // Recover Graphics2D
14       Graphics2D g2 = (Graphics2D) g;
15
16          // Construct a rectangle and draw it
17          Rectangle box = new Rectangle(5, 10, 20, 30);
18          g2.draw(box);
19
20          // Move rectangle 15 units to the right and 25 units down
21          box.translate(15, 25);
22
23          // Draw moved rectangle
24          g2.draw(box);
25       }
26    }

In order to see the drawing, one task remains. You need to display the frame into which you added a component object. Follow these steps:

  1. Construct a frame as described in the preceding section.

  2. Construct an object of your component class:

    RectangleComponent component = new RectangleComponent();
  3. Add the component to the frame:

    frame.add(component);
  4. Make the frame visible, as described in the preceding section.

The following listing shows the complete process.

ch02/rectangles/RectangleViewer.java

1  import javax.swing.JFrame;
2
3  public class RectangleViewer
4  {
5     public static void main(String[] args)
6      {
7        JFrame frame = new JFrame();
8
9        frame.setSize(300, 400);
10        frame.setTitle("Two rectangles");
11        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
12
13        RectangleComponent component = new RectangleComponent();
14        frame.add(component);
15
16        frame.setVisible(true);
17      }
18  }

Note that the rectangle drawing program consists of two classes:

  • The RectangleComponent class, whose paintComponent method produces the drawing.

  • The RectangleViewer class, whose main method constructs a frame and a RectangleComponent, adds the component to the frame, and makes the frame visible.

Drawing Rectangles

30. How do you modify the program to draw one rectangle and one square?

31. What happens if you call g.draw(box) instead of g2.draw(box)?

Ellipses, Lines, Text, and Color

In Section 2.12 you learned how to write a program that draws rectangles. In this section you will learn how to draw other shapes: ellipses and lines. With these graphical elements, you can draw quite a few interesting pictures.

Ellipses and Circles

To draw an ellipse, you specify its bounding box (see Figure 24) in the same way that you would specify a rectangle, namely by the x- and y-coordinates of the top-left corner and the width and height of the box.

However, there is no simple Ellipse class that you can use. Instead, you must use one of the two classes Ellipse2D.Float and Ellipse2D.Double, depending on whether you want to store the ellipse coordinates as single- or double-precision floating-point values. Because the latter are more convenient to use in Java, we will always use the Ellipse2D.Double class. Here is how you construct an ellipse:

Ellipse2D.Double ellipse = new Ellipse2D.Double(x, y, width, height);

Note

The Ellipse2D.Double and Line2D.Double classes describe graphical shapes.

The class name Ellipse2D.Double looks different from the class names that you have encountered up to now. It consists of two class names Ellipse2D and Double separated by a period (.). This indicates that Ellipse2D.Double is a so-called inner class inside Ellipse2D. When constructing and using ellipses, you don't actually need to worry about the fact that Ellipse2D.Double is an inner class—just think of it as a class with a long name. However, in the import statement at the top of your program, you must be careful that you import only the outer class:

An Ellipse and Its Bounding Box

Figure 2.24. An Ellipse and Its Bounding Box

import java.awt.geom.Ellipse2D;

Drawing an ellipse is easy: Use exactly the same draw method of the Graphics2D class that you used for drawing rectangles.

g2.draw(ellipse);

To draw a circle, simply set the width and height to the same values:

Ellipse2D.Double circle = new Ellipse2D.Double(x, y, diameter, diameter);
g2.draw(circle);

Notice that (x, y) is the top-left corner of the bounding box, not the center of the circle.

Lines

To draw a line, use an object of the Line2D.Double class. A line is constructed by specifying its two end points. You can do this in two ways. Simply give the x- and y-coordinates of both end points:

Line2D.Double segment = new Line2D.Double(x1, y1, x2, y2);

Or specify each end point as an object of the Point2D.Double class:

Point2D.Double from = new Point2D.Double(x1, y1);
Point2D.Double to = new Point2D.Double(x2, y2);

Line2D.Double segment = new Line2D.Double(from, to);

The second option is more object-oriented and is often more useful, particularly if the point objects can be reused elsewhere in the same drawing.

Drawing Text

You often want to put text inside a drawing, for example, to label some of the parts. Use the drawString method of the Graphics2D class to draw a string anywhere in a window. You must specify the string and the x- and y-coordinates of the basepoint of the first character in the string (see Figure 25). For example,

g2.drawString("Message", 50, 100);

Note

The drawString method draws a string, starting at its basepoint.

Basepoint and Baseline

Figure 2.25. Basepoint and Baseline

Colors

When you first start drawing, all shapes and strings are drawn with a black pen. To change the color, you need to supply an object of type Color. Java uses the RGB color model. That is, you specify a color by the amounts of the primary colors—red, green, and blue—that make up the color. The amounts are given as integers between 0 (primary color not present) and 255 (maximum amount present). For example,

Color magenta = new Color(255, 0, 255);

constructs a Color object with maximum red, no green, and maximum blue, yielding a bright purple color called magenta.

For your convenience, a variety of colors have been declared in the Color class. Table 4 shows those colors and their RGB values. For example, Color.PINK has been declared to be the same color as new Color(255, 175, 175).

To draw a shape in a different color, first set the color of the Graphics2D object, then call the draw method:

g2.setColor(Color.RED);
g2.draw(circle); // Draws the shape in red

Note

When you set a new color in the graphics context, it is used for subsequent drawing operations.

If you want to color the inside of the shape, use the fill method instead of the draw method. For example,

g2.fill(circle);

fills the inside of the circle with the current color.

Table 2.4. Predefined Colors

Color

RGB Value

Predefined Colors
An Alien Face

Figure 2.26. An Alien Face

The following program puts all these shapes to work, creating a simple drawing (see Figure 26).

ch02/face/FaceComponent.java

1  import java.awt.Color;
2  import java.awt.Graphics;
3  import java.awt.Graphics2D;
4  import java.awt.Rectangle;
5  import java.awt.geom.Ellipse2D;
6  import java.awt.geom.Line2D;
7  import javax.swing.JComponent;
8
9  /*
10     A component that draws an alien face.
11  */
12  public class FaceComponent extends JComponent
13  {
14     public void paintComponent(Graphics g)
15     {
16        // Recover Graphics2D
17        Graphics2D g2 = (Graphics2D) g;
18
19        // Draw the head
20        Ellipse2D.Double head = new Ellipse2D.Double(5, 10, 100, 150);
21        g2.draw(head);
22
23        // Draw the eyes
24        g2.setColor(Color.GREEN);
25        Rectangle eye = new Rectangle(25, 70, 15, 15);
26        g2.fill(eye);
27        eye.translate(50, 0);
28        g2.fill(eye);
29
30        // Draw the mouth
31        Line2D.Double mouth = new Line2D.Double(30, 110, 80, 110);
32        g2.setColor(Color.RED);
33        g2.draw(mouth);
34
35        // Draw the greeting
36        g2.setColor(Color.BLUE);
37        g2.drawString("Hello, World!", 5, 175);
38     }
39  }

ch02/face/FaceViewer.java

1  import javax.swing.JFrame;
2
3  public class FaceViewer
4  {
5     public static void main(String[] args)
6      {
7        JFrame frame = new JFrame();
8        frame.setSize(150, 250);
9        frame.setTitle("An Alien Face");
10        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
11
12        FaceComponent component = new FaceComponent();
13        frame.add(component);
14
15        frame.setVisible(true);
16      }
17  }
An Alien Face

33. Give instructions to draw a letter "V" by drawing two line segments.

34. Give instructions to draw a string consisting of the letter "V".

35. What are the RGB color values of Color.BLUE?

36. How do you draw a yellow square on a red background?

Summary of Learning Objectives

Use integers and floating-point numbers.

  • A type specifies a set of values and the operations that can be carried out with the values.

  • The double type denotes floating-point numbers that can have fractional parts.

  • In Java, the number types are primitive types, and numbers are not objects.

  • Numbers can be combined by arithmetic operators such as +, -, and *.

Write variable declarations in Java.

  • You use variables to store values that you want to use at a later time. A variable has a type, a name, and a value.

  • Identifiers for variables, methods, and classes are composed of letters, digits, and the underscore character.

  • By convention, variable names should start with a lowercase letter.

Explain the processes of variable assignment and initialization.

  • Use the assignment operator (=) to change the value of a variable.

  • All variables must be initialized before you access them.

Declare objects, classes, and methods.

  • Objects are entities in your program that you manipulate by calling methods.

  • A method is a sequence of instructions that accesses the data of an object.

  • A class declares the methods that you can apply to its objects.

  • The public interface of a class specifies what you can do with its objects. The hidden implementation describes how these actions are carried out.

Recognize implicit parameters, explicit parameters, and return values of methods.

  • A parameter is an input to a method.

  • The implicit parameter of a method call is the object on which the method is invoked. All other parameters are explicit parameters.

  • The return value of a method is a result that the method has computed for use by the code that called it.

Use constructors to construct new objects.

  • Use the new operator, followed by a class name and parameters, to construct new objects.

Classify methods as accessor and mutator methods.

  • An accessor method does not change the internal data of its implicit parameter. A mutator method changes the data.

Use the API documentation for finding method descriptions and packages.

  • The API (Application Programming Interface) documentation lists the classes and methods of the Java library.

  • Java classes are grouped into packages. Use the import statement to use classes that are declared in other packages.

Write programs that test behavior of methods.

  • A test program verifies that methods behave as expected.

  • Determining the expected result in advance is an important part of testing.

Describe how multiple object references can refer to the same object.

  • An object reference describes the location of an object.

  • Multiple object variables can contain references to the same object.

  • Number variables store numbers. Object variables store references.

Write programs that display frame windows.

  • To show a frame, construct a JFrame object, set its size, and make it visible.

  • In order to display a drawing in a frame, declare a class that extends the JComponent class.

  • Place drawing instructions inside the paintComponent method. That method is called whenever the component needs to be repainted.

  • Use a cast to recover the Graphics2D object from the Graphics parameter of the paintComponent method.

  • Applets are programs that run inside a web browser.

  • To run an applet, you need an HTML file with the applet tag.

  • You view applets with the applet viewer or a Java-enabled browser.

Use the Java API for drawing simple figures.

  • The Ellipse2D.Double and Line2D.Double classes describe graphical shapes.

  • The drawString method draws a string, starting at its basepoint.

  • When you set a new color in the graphics context, it is used for subsequent drawing operations.

Classes, Objects, and Methods Introduced in this Chapter

java.awt.Color                             java.awt.Rectangle
java.awt.Component                            getX
   getHeight                                  getY
   getWidth                                   getHeight
   setSize                                    getWidth
   setVisible                                 setSize
java.awt.Frame                                translate
   setTitle                                java.lang.String
java.awt.geom.Ellipse2D.Double                length
java.awt.geom.Line2D.Double                   replace
java.awt.geom.Point2D.Double                  toLowerCase
java.awt.Graphics                             toUpperCase
   setColor                                javax.swing.JComponent
java.awt.Graphics2D                           paintComponent
   draw                                    javax.swing.JFrame
   drawString                                 setDefaultCloseOperation
   fill

Media Resources

  • Worked Example How Many Days Have You Been Alive?

  • Worked Example Working with Pictures

  • • Lab Exercises

  • Media Resources
  • Media Resources
  • Media Resources
  • Media Resources
  • Media Resources

Review Exercises

R2.1 Explain the difference between an object and an object reference.

R2.2 Explain the difference between an object and an object variable.

R2.3 Explain the difference between an object and a class.

R2.4 Give the Java code for constructing an object of class Rectangle, and for declaring an object variable of class Rectangle.

R2.5 Explain the difference between the = symbol in Java and in mathematics.

R2.6 Give Java code for objects with the following descriptions:

  1. A rectangle with center (100, 100) and all side lengths equal to 50

  2. A string with the contents "Hello, Dave"

Create objects, not object variables.

R2.7 Repeat Exercise R2.6, but now declare object variables that are initialized with the required objects.

R2.8 Write a Java statement to initialize a variable square with a rectangle object whose top left corner is (10, 20) and whose sides all have length 40. Then write a statement that replaces square with a rectangle of the same size and top left corner (20, 20).

R2.9 Write Java statements that initialize two variables square1 and square2 to refer to the same square with center (20, 20) and side length 40.

R2.10 Write Java statements that initialize a string message with "Hello" and then change it to "HELLO". Use the toUpperCase method.

R2.11 Write Java statements that initialize a string message with "Hello" and then change it to "hello". Use the replace method.

R2.12 Find the errors in the following statements:

  1. Rectangle r = (5, 10, 15, 20);

  2. double width = Rectangle(5, 10, 15, 20).getWidth();

  3. Rectangle r;

    r.translate(15, 25);

  4. r = new Rectangle();

    r.translate("far, far away!");

R2.13 Name two accessor methods and two mutator methods of the Rectangle class.

R2.14 Look into the API documentation of the Rectangle class and locate the method

void add(int newx, int newy)

Read through the method documentation. Then determine the result of the following statements:

Rectangle box = new Rectangle(5, 10, 20, 30);
box.add(0, 0);

If you are not sure, write a small test program.

R2.15 What is the difference between a console application and a graphical application?

R2.16 Who calls the paintComponent method of a component? When does the call to the paintComponent method occur?

R2.17 Why does the parameter of the paintComponent method have type Graphics and not Graphics2D?

R2.18 What is the purpose of a graphics context?

R2.19 Why are separate viewer and component classes used for graphical programs?

R2.20 How do you specify a text color?

Programming Exercises

P2.1 Write an AreaTester program that constructs a Rectangle object and then computes and prints its area. Use the getWidth and getHeight methods. Also print the expected answer.

P2.2 Write a PerimeterTester program that constructs a Rectangle object and then computes and prints its perimeter. Use the getWidth and getHeight methods. Also print the expected answer.

P2.3 Write a program called FourRectanglePrinter that constructs a Rectangle object, prints its location by calling System.out.println(box), and then translates and prints it three more times, so that, if the rectangles were drawn, they would form one large rectangle:

Programming Exercises

Your program will not produce a drawing. It will simply print the locations of the four rectangles.

P2.4 Write a GrowSquarePrinter program that constructs a Rectangle object square representing a square with top-left corner (100, 100) and side length 50, prints its location by calling System.out.println(square), applies the translate and grow methods and calls System.out.println(square) again. The calls to translate and grow should modify the square so that it has twice the size and the same top-left corner as the original. If the squares were drawn, they would look like this:

Programming Exercises

Your program will not produce a drawing. It will simply print the locations of square before and after calling the mutator methods.

Look up the description of the grow method in the API documentation.

P2.5 The intersection method computes the intersection of two rectangles—that is, the rectangle that would be formed by two overlapping rectangles if they were drawn:

Programming Exercises

You call this method as follows:

Rectangle r3 = r1.intersection(r2);

Write a program IntersectionPrinter that constructs two rectangle objects, prints them as described in Exercise P2.3, and then prints the rectangle object that describes the intersection. Then the program should print the result of the intersection method when the rectangles do not overlap. Add a comment to your program that explains how you can tell whether the resulting rectangle is empty.

P2.6 In this exercise, you will explore a simple way of visualizing a Rectangle object. The setBounds method of the JFrame class moves a frame window to a given rectangle. Complete the following program to visually show the translate method of the Rectangle class:

import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class TranslateDemo
{
   public static void main(String[] args)
   {
      // Construct a frame and show it
      JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);

      // Your work goes here:
      // Construct a rectangle and set the frame bounds

      JOptionPane.showMessageDialog(frame, "Click OK to continue");

      // Your work goes here:
      // Move the rectangle and set the frame bounds again
   }
}

P2.7 In the Java library, a color is specified by its red, green, and blue components between 0 and 255 (see Table 4 on page 67). Write a program BrighterDemo that constructs a Color object with red, green, and blue values of 50, 100, and 150. Then apply the brighter method and print the red, green, and blue values of the resulting color. (You won't actually see the color—see the next exercise on how to display the color.)

P2.8 Repeat Exercise P2.7, but place your code into the following class. Then the color will be displayed.

import java.awt.Color;
import javax.swing.JFrame;

public class BrighterDemo
{
   public static void main(String[] args)
   {
      JFrame frame = new JFrame();
      frame.setSize(200, 200);
      Color myColor = ...;
      frame.getContentPane().setBackground(myColor);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
   }
}

P2.9 Repeat Exercise P2.7, but apply the darker method twice to the object Color.RED. Call your class DarkerDemo.

P2.10 The Random class implements a random number generator, which produces sequences of numbers that appear to be random. To generate random integers, you construct an object of the Random class, and then apply the nextInt method. For example, the call generator.nextInt(6) gives you a random number between 0 and 5.

Write a program DieSimulator that uses the Random class to simulate the cast of a die, printing a random number between 1 and 6 every time that the program is run.

P2.11 Write a program LotteryPrinter that picks a combination in a lottery. In this lottery, players can choose 6 numbers (possibly repeated) between 1 and 49. (In a real lottery, repetitions aren't allowed, but we haven't yet discussed the programming constructs that would be required to deal with that problem.) Your program should print out a sentence such as "Play this combination—it'll make you rich!", followed by a lottery combination.

P2.12 Write a program ReplaceTester that encodes a string by replacing all letters "i" with "!" and all letters "s" with "$". Use the replace method. Demonstrate that you can correctly encode the string "Mississippi". Print both the actual and expected result.

P2.13 Write a program HollePrinter that switches the letters "e" and "o" in a string. Use the replace method repeatedly. Demonstrate that the string "Hello, World!" turns into "Holle, Werld!"

P2.14 Write a graphics program that draws your name in red, contained inside a blue rectangle. Provide a class NameViewer and a class NameComponent.

P2.15 Write a graphics program that draws 12 strings, one each for the 12 standard colors, besides Color.WHITE, each in its own color. Provide a class ColorNameViewer and a class ColorNameComponent.

P2.16 Write a program that draws two solid squares: one in pink and one in purple. Use a standard color for one of them and a custom color for the other. Provide a class TwoSquareViewer and a class TwoSquareComponent.

P2.17 Write a program that fills the window with a large ellipse, with a black outline and filled with your favorite color. The ellipse should touch the window boundaries, even if the window is resized.

P2.18 Write a program to plot the following face.

Programming Exercises

Provide a class FaceViewer and a class FaceComponent.

Programming Projects

Project 2.1 The GregorianCalendar class describes a point in time, as measured by the Gregorian calendar, the standard calendar that is commonly used throughout the world today. You construct a GregorianCalendar object from a year, month, and day of the month, like this:

GregorianCalendar cal = new GregorianCalendar(); // Today's date
GregorianCalendar eckertsBirthday = new GregorianCalendar(1919,
      Calendar.APRIL, 9);

Use the values Calendar.JANUARY . . . Calendar.DECEMBER to specify the month.

The add method can be used to add a number of days to a GregorianCalendar object:

cal.add(Calendar.DAY_OF_MONTH, 10); // Now cal is ten days from today

This is a mutator method—it changes the cal object.

The get method can be used to query a given GregorianCalendar object:

int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
int month = cal.get(Calendar.MONTH);
int year = cal.get(Calendar.YEAR);
int weekday = cal.get(Calendar.DAY_OF_WEEK);
   // 1 is Sunday, 2 is Monday, ..., 7 is Saturday

Your task is to write a program that prints the following information:

  • The date and weekday that is 100 days from today

  • The weekday of your birthday

  • The date that is 10,000 days from your birthday

Use the birthday of a computer scientist if you don't want to reveal your own birthday.

Project 2.2 Run the following program:

import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class FrameViewer
{
   public static void main(String[] args)
   {
JFrame frame = new JFrame();
      frame.setSize(200, 200);
      JLabel label = new JLabel("Hello, World!");
      label.setOpaque(true);
      label.setBackground(Color.PINK);
      frame.add(label);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
   }
}

Modify the program as follows:

  • Double the frame size.

  • Change the greeting to "Hello, your name!".

  • Change the background color to pale green (see Exercise P2.7).

  • For extra credit, add an image of yourself. (Hint: Construct an ImageIcon.)

Answers to Self-Check Questions

  1. int and String

  2. double

  3. An int is not an object, and you cannot call a method on it.

  4. (x + y) * 0.5

  5. Only the first two are legal identifiers.

  6. String myName = "John Q. Public";

  7. No, the left-hand side of the = operator must be a variable.

  8. greeting = "Hello, Nina!";

    Note that

    String greeting = "Hello, Nina!";

    is not the right answer—that statement declares a new variable.

  9. river.length() or "Mississippi".length()

  10. System.out.println(greeting.toUpperCase()); or

    System.out.println("Hello, World!".toUpperCase());
  11. It is not legal. The variable river has type String. The println method is not a method of the String class.

  12. The implicit parameter is river. There is no explicit parameter. The return value is 11.

  13. "Missississi"

  14. 12

  15. As public String toUpperCase(), with no explicit parameter and return type String.

  16. new Rectangle(90, 90, 20, 20)

  17. 0

  18. An accessor—it doesn't modify the original string but returns a new string with uppercase letters.

  19. box.translate(−5, −10), provided the method is called immediately after storing the new rectangle into box.

  20. toLowerCase

  21. "Hello, Space !"—only the leading and trailing spaces are trimmed.

  22. Add the statement import java.util.Random; at the top of your program.

  23. x: 30, y: 25

  24. Because the translate method doesn't modify the shape of the rectangle.

  25. Now greeting and greeting2 both refer to the same String object.

  26. Both variables still refer to the same string, and the string has not been modified. Recall that the toUpperCase method constructs a new string that contains uppercase characters, leaving the original string unchanged.

  27. Modify the EmptyFrameViewer program as follows:

    frame.setSize(300, 300);
    frame.setTitle("Hello, World!");
  28. Construct two JFrame objects, set each of their sizes, and call setVisible(true) on each of them.

  29. Rectangle box = new Rectangle(5, 10, 20, 20);

  30. Replace the call to box.translate(15, 25) with

    box = new Rectangle(20, 35, 20, 20);
  31. The compiler complains that g doesn't have a draw method.

  32. g2.draw(new Ellipse2D.Double(75, 75, 50, 50));

  33. Line2D.Double segment1 = new Line2D.Double(0, 0, 10, 30);
    g2.draw(segment1);
    Line2D.Double segment2 = new Line2D.Double(10, 30, 20, 0);
    g2.draw(segment2);
  34. g2.drawString("V", 0, 30);

  35. 0, 0, 255

  36. First fill a big red square, then fill a small yellow square inside:

    g2.setColor(Color.RED);
    g2.fill(new Rectangle(0, 0, 200, 200));
    g2.setColor(Color.YELLOW);
    g2.fill(new Rectangle(50, 50, 100, 100));
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.205.27