Creating Your First Object - Working with Information in New Ways - Sams Teach Yourself Java in 24 Hours, 7th Edition (2014)

Sams Teach Yourself Java in 24 Hours, 7th Edition (2014)

Part III: Working with Information in New Ways

Hour 10. Creating Your First Object

THIS HOUR’S TO-DO LIST:

Image Create an object.

Image Describe an object with attributes.

Image Determine how objects behave.

Image Combine objects.

Image Inherit from other objects.

Image Convert objects and other types of information.

One of the more fearsome examples of jargon that you encounter during these 24 hours is object-oriented programming (OOP). This complicated term describes, in an elegant way, what a computer program is and how it works.

Before OOP, a computer program was usually described under the simplest definition you’ve learned in this book: a set of instructions listed in a file and handled in some kind of reliable order.

By thinking of a program as a collection of objects, you can figure out the tasks a program must accomplish and assign the tasks to the objects where they best belong.

How Object-Oriented Programming Works

You can think of the Java programs you create as objects, just like physical objects that exist in the real world. Objects exist independently of other objects, interact in specific ways, and can be combined with other objects to form something bigger. If you think of a computer program as a group of objects that interact with each other, you can design a program that’s more reliable, easier to understand, and reusable in other projects.

In Hour 23, “Creating Java2D Graphics,” you create a Java program that displays pie graphs—circles with different-colored pie slices to represent data (see Figure 10.1). A pie chart is an object that is made up of smaller objects—individual slices of different colors, a legend identifying what each slice represents, and a title.

Image

FIGURE 10.1 A Java program that displays a pie chart.

Each object has things that make it different from other objects. Pie charts are circular, whereas bar graphs represent data as a series of rectangles. If you break down computer programs in the same way a pie chart is broken down, you’re engaging in OOP.

In OOP, an object contains two things: attributes and behavior. Attributes are things that describe the object and show how it is different from other objects. Behavior is what an object does.

You create objects in Java by using a class as a template. A class is a master copy of the object that determines the attributes and behavior an object should have. The term class should be familiar to you because Java programs are called classes. Every program you create with Java is a class that you can use as a template for the creation of new objects. As an example, any Java program that uses strings is using objects created from the String class. This class contains attributes that determine what a String object is and behavior that controls what String objects can do.

With OOP, a computer program is a group of objects that work together to get something done. Some simple programs might seem as though they consist of only one object: the class file. However, even those programs are using other objects to get work done.

Objects in Action

Consider the case of the program that displays a pie chart. A PieChart object could consist of the following:

Image Behavior to calculate the size of each pie slice

Image Behavior to draw the chart

Image An attribute to store the title of the chart


Note

An autodialer is software that uses a device called a modem to dial a series of phone numbers in sequence. The purpose of such a program is to find other computers that answer the phone, so you can call them later to see what they are.

Readers younger than 30 might find it hard to believe that computers used to make connections to each other with phone calls. You had to know a computer’s phone number to connect to it, and if it already was talking to another computer, you got a busy signal.

Now I probably need to explain what a busy signal is.

To quote the poet T.S. Eliot, “I grow old ... I grow old.”


It might seem odd to ask the PieChart object to draw itself because graphs don’t draw themselves in the real world. Objects in OOP work for themselves whenever possible. This capability makes it easier to incorporate them in other programs. If a PieChart object did not know how to draw itself, for instance, every time you used that PieChart object in another program, you would have to create behavior to draw it.

For another example of OOP, consider the autodialer program that Matthew Broderick’s character used in the classic hacker movie WarGames to find computers he could break into.

Using an autodialer today would attract the attention of your local phone company and law enforcement. Back in the 1980s, it was a good way to be rebellious without leaving the house. David Lightman (the character portrayed by Broderick) used his autodialer to look for a video game company’s private computer system—he wanted to play the company’s new game before it was released. Instead, Lightman found a secret government computer that could play everything from chess to Global Thermonuclear War.

An autodialer, like any computer program, can be thought of as a group of objects that work together. It could be broken down into the following:

Image A Modem object, which knows its attributes such as connection speed and has behavior—for example, it can make the modem dial a number and detect that another computer system has answered a call

Image A Monitor object, which keeps track of what numbers are called and which ones are successful

Each object exists independently of the other.

One advantage of designing a completely independent Modem object is that it could be used in other programs that need modem functionality.

Another reason to use self-contained objects is that they are easier to debug. Computer programs quickly become unwieldy in size. If you’re debugging something like a Modem object and you know it’s not dependent on anything else, you can focus on making sure the Modem object does the job it’s supposed to do and holds the information that it needs to do its job.

Learning an object-oriented language such as Java as your first programming language can be advantageous because you’re not unlearning the habits of other styles of programming.

What Objects Are

Objects are created by using a class of objects as a template. The following statements create a class:

public class Modem {
}

An object created from this class can’t do anything because it doesn’t have any attributes or behavior. You need to add those to make the class useful, as in the following statements:

public class Modem {
int speed;

public void displaySpeed() {
System.out.println("Speed: " + speed);
}
}

The Modem class now should be starting to look like programs you’ve written during Hours 1 through 9. The Modem class begins with a class statement, except that it has the word public in it. This means that the class is available for use by the public—in other words, by any program that wants to use Modem objects.

The first part of the Modem class creates an integer variable called speed. This variable is an attribute of the object.

The second part of the Modem class is a method called displaySpeed(). This method is part of the object’s behavior. It contains one statement, System.out.println(), which reveals the modem’s speed value.

An object’s variables are called instance variables or member variables.

If you want to use a Modem object in a program, you create the object with the following statement:

Modem device = new Modem();

This statement creates a Modem object called device. After you have created an object, you can set its variables and call its methods. Here’s how to set the value of the speed variable of the device object:

device.speed = 28800;

To make this modem display its speed by calling the displaySpeed() method, you call the method:

device.displaySpeed();

The Modem object named device could respond to this statement by displaying the text “Speed: 28800.”

Understanding Inheritance

A big advantage to OOP is inheritance, which enables one object to inherit behavior and attributes from another object.

When you start creating objects, you sometimes find that a new object you want is a lot like an object you already have.

What if David Lightman wanted an object that could handle error correction and other advanced modem features that weren’t around in 1983 when WarGames was released? Lightman could create a new ErrorCorrectionModem object by copying the statements of the Modem object and revising them. However, if most of the behavior and attributes of ErrorCorrectionModem are the same as those of Modem, this is a lot of unnecessary work. It also means that Lightman would have two separate programs to update if something needed to be changed later.

Through inheritance, a programmer can create a new class of objects by defining how they are different than an existing class. Lightman could make ErrorCorrectionModem inherit from Modem, and all he would need to write are things that make error-correction modems different than modems.

A class of objects inherits from another class by using the extends statement. The following is a skeleton of an ErrorCorrectionModem class that inherits from the Modem class:

public class ErrorCorrectionModem extends Modem {
// program goes here
}

Building an Inheritance Hierarchy

Inheritance, which enables a variety of related classes to be developed without redundant work, makes it possible for code to be passed down from one class to another class to another class. This grouping of classes is called a class hierarchy, and all the standard classes you can use in your Java programs are part of a hierarchy.

Understanding a hierarchy is easier if you understand subclasses and superclasses. A class that inherits from another class is called a subclass. The class that is inherited from is called a superclass.

In the preceding WarGames example, the Modem class is the superclass of the ErrorCorrectionModem class. ErrorCorrectionModem is the subclass of Modem.

A class can have more than one class that inherits from it in the hierarchy—another subclass of Modem could be ISDNModem because ISDN modems have behavior and attributes that make them different from error-correcting modems. If there was a subclass ofErrorCorrectionModem such as InternalErrorCorrectionModem, it would inherit from all classes above it in the hierarchy—both ErrorCorrectionModem and Modem. These inheritance relationships are shown in Figure 10.2.

Image

FIGURE 10.2 An example of a class hierarchy.

The classes that make up the standard Java language make full use of inheritance, so understanding it is essential. You learn more about inheritance during Hour 12, “Making the Most of Existing Objects.”

Converting Objects and Simple Variables

One of the most common tasks you need to accomplish in Java is to convert information from one form into another. Several types of conversions you can do include

Image Converting an object into another object

Image Converting a simple variable into another type of variable

Image Using an object to create a simple variable

Image Using a simple variable to create an object

Simple variables are the basic data types you learned about during Hour 5, “Storing and Changing Information in a Program.” Some of these types are int, float, char, long, double, byte, and short.


Note

When a method such as System.out.println() requires a string argument, you can use the + operator to combine several different types of information in that argument. As long as one of the things being combined is a string, the combined argument is converted into a string.


When using a method or an expression in a program, you must use the right type of information that’s expected by these methods and expressions. A method that expects a Calendar object must receive a Calendar object, for instance. If you used a method that takes a single integer argument and you sent it a floating-point number instead, an error would occur when you attempted to compile the program.

Converting information to a new form is called casting. Casting produces a new value that is a different type of variable or object than its source. You don’t actually change the value when casting. Instead, a new variable or object is created in the format you need.

The terms source and destination are useful when discussing the concept of casting. The source is some kind of information in its original form—whether it’s a variable or an object. The destination is the converted version of the source in a new form.

Casting Simple Variables

With simple variables, casting occurs most commonly between numeric variables such as integers and floating-point numbers. One type of variable that cannot be used in any casting is Boolean values.

To cast information into a new format, you precede it with the new format surrounded by parentheses. For example, if you want to cast something into a long variable, you precede it with (long). The following statements cast a float value into an int:

float source = 7.06F;
int destination = (int) source;

In variable casting where the destination holds larger values than the source, the value is converted easily, such as when a byte is cast into an int. A byte holds values from –128 to 127, whereas an int holds values from –2.1 billion to 2.1 billion. No matter what value the byte variable holds, the new int variable has plenty of room for it.

You sometimes can use a variable in a different format without casting it at all. For example, you can use char variables as if they were int variables. Also, you can use int variables as if they were long variables, and anything can be used as a double.

In most cases, because the destination provides more room than the source, the information is converted without changing its value. The main exceptions occur when an int or long variable is cast to a float, or a long is cast into a double.

When you are converting information from a larger variable type into a smaller type, you must explicitly cast it, as in the following statements:

int xNum = 103;
byte val = (byte) xNum;

Here, casting converts an integer value called xNum into a byte variable called val. This is an example where the destination variable holds a smaller range of values than the source variable. A byte holds integer values ranging from –128 to 127, and an int holds a much larger range of integer values.

When the source variable in a casting operation has a value that isn’t enabled in the destination variable, Java changes the value to make the cast fit successfully. This can produce unexpected results if you’re not expecting the change.

Casting Objects

You can cast objects into other objects when the source and destination are related by inheritance. One class must be a subclass of the other.

Some objects do not require casting at all. You can use an object where any of its superclasses are expected. All objects in Java are subclasses of the Object class, so you can use any object as an argument when an Object is expected.

You also can use an object where one of its subclasses is expected. However, because subclasses usually contain more information than their superclasses, you might lose some of this information. If the object doesn’t have a method that the subclass would contain, an error results if that missing method is used in the program.

To use an object in place of one of its subclasses, you must cast it explicitly with statements such as the following:

public void paintComponent(Graphics comp) {
Graphics2D comp2D = (Graphics2D) comp;
}

This casts a Graphics object called comp into a Graphics2D object. You don’t lose any information in the cast, but you gain all the methods and variables the subclass defines.

Converting Simple Variables to Objects and Back

One thing you can’t do is cast an object to a simple variable or a simple variable to an object. There are classes in Java for each of the simple variable types including Boolean, Byte, Character, Double, Float, Integer, Long, and Short. All these classes are capitalized because they are objects, not simple variable types.

Using methods defined in each of these classes, you can create an object using a variable’s value as an argument. The following statement creates an Integer object with the value 5309:

Integer suffix = new Integer(5309);

After you have created an object like this, you can use it like any other object. When you want to use that value again as a simple variable, the class has methods to perform that conversion. To get an int value from the preceding suffix object, you could use the following statement:

int newSuffix = suffix.intValue();

This statement causes the newSuffix variable to have the value 5309, expressed as an int value. One common casting from an object to a variable is to use a string in a numeric expression. When the string’s value could become an integer, this can be done using the parseInt() method of the Integer class, as in this example:

String count = "25";
int myCount = Integer.parseInt(count);

This converts a string with the text “25” into an integer with the value 25. If the string value was not a valid integer, the conversion would not work.

The next project you create is an application that converts a string value in a command-line argument to a numeric value, a common technique when you’re taking input from a user at the command line.

Return to your Java24 project in NetBeans, choose File, New File, and then create a new Empty Java File named NewRoot. Enter Listing 10.1 in the source editor and remember to save the file.

LISTING 10.1 The Full Text of NewRoot.java


1: package com.java24hours;
2:
3: class NewRoot {
4: public static void main(String[] arguments) {
5: int number = 100;
6: if (arguments.length > 0) {
7: number = Integer.parseInt(arguments[0]);
8: }
9: System.out.println("The square root of "
10: + number
11: + " is "
12: + Math.sqrt(number)
13: );
14: }
15: }


Before you run the program, you must configure NetBeans to run it with a command-line argument. Choose the menu command Run, Set Project Configuration, Customize. The Project Properties window opens. Enter com.java24hours.NewRoot as the Main Class and 9025 in the Arguments field. Click OK to close the dialog.

To run the program, choose Run, Run Main Project (instead of Run, Run File). The program displays the number and its square root, as shown in Figure 10.3.

Image

FIGURE 10.3 The output of the NewRoot program.

The NewRoot application is an expansion of an earlier tutorial from Hour 4, “Understanding How Java Programs Work,” that displayed the square root of the integer 225.

That program would have been more useful if it took a number submitted by a user and displayed its square root. This requires conversion from a string to an integer. All command-line arguments are stored as elements of a String array, so you must cast them to numbers before using them in mathematical expressions.

To create an integer value based on the contents of a string, you call the Integer.parseInt() method with the string as the only argument, as in Line 7:

number = Integer.parseInt(arguments[0]);

The arguments[0] array element holds the first command-line argument submitted when the application is run. When the program was run with “9025” as an argument, the string “9025” was converted to the int 9025.

Autoboxing and Unboxing

Every one of the basic data types in Java has a corresponding object class: boolean (Boolean class), byte (Byte), char (Character), double (Double), float (Float), int (Integer), long (Long), and short (Short).

For each of these pairs, the information has identical value. The only difference between them is the format the value takes. An integer value such as 413 could be represented by either an int or an object of the Integer class.

Java’s autoboxing and unboxing capabilities make it possible to use the basic data type and object forms of a value interchangeably.

Autoboxing casts a simple variable value to the corresponding class.

Unboxing casts an object to the corresponding simple value.

These features work behind the scenes, assuring that when you are expecting a simple data type like float, an object is converted to the matching data type with the same value. When you’re expecting an object like Float, a data type is converted to an object as necessary.

The following statements show where autoboxing and unboxing come in handy:

Float total = new 1.3F;
float sum = total / 5;

In early versions of Java, this code would fail with two errors. The first statement assigns a literal float value of 1.3 to a Float object (not allowed), and the second statement divides a Float object and assigns it to a float type (not allowed). It works perfectly in Java now, because the first statement boxes the literal into an object and the second unboxes an object to a primitive type. Java automatically makes the statements work, resulting in sum being equal to 0.26.

Earlier in this hour, you saw an example of how to create an Integer object:

Integer suffix = new Integer(5309);

Because of autoboxing and unboxing, the following statement also does the same thing:

Integer suffix = 5309;

Java recognizes that the int value 5309 is being stored in an Integer object, so it is converted automatically.

Creating an Object

To see a working example of classes and inheritance in this hour’s next project, you create classes that represent two types of objects: cable modems, which are implemented as the CableModem class, and DSL modems, which are implemented as the DslModem class. The workshop focuses on simple attributes and behavior for these objects:

Image Each object should have a speed that it can display.

Image Each object should be able to connect to the Internet.

One thing that cable modems and DSL modems have in common is that they both have a speed. Because this is something they share, it can be put into a class that is the superclass of both the CableModem and DslModem classes. Call this class Modem. In NetBeans, create a new empty Java class called Modem. Enter Listing 10.2 in the source editor and save the file.

LISTING 10.2 The Full Text of Modem.java


1: package com.java24hours;
2:
3: public class Modem {
4: int speed;
5:
6: public void displaySpeed() {
7: System.out.println("Speed: " + speed);
8: }
9: }


This file is compiled automatically as Modem.class. You cannot run this program directly, but you can use it in other classes. The Modem class can handle one of the things that the CableModem and DslModem classes have in common. By using the extends statement when you are creating the CableModem and DslModem classes, you can make each of them a subclass of Modem.

Start a new Empty Java File in NetBeans with the class name CableModem. Enter Listing 10.3 and save the file.

LISTING 10.3 The Full Text of CableModem.java


1: package com.java24hours;
2:
3: public class CableModem extends Modem {
4: String method = "cable connection";
5:
6: public void connect() {
7: System.out.println("Connecting to the Internet ...");
8: System.out.println("Using a " + method);
9: }
10: }


Create a third file in NetBeans named DslModem. Enter Listing 10.4 and save the file.

LISTING 10.4 The Full Text of DslModem.java


1: package com.java24hours;
2:
3: public class DslModem extends Modem {
4: String method = "DSL phone connection";
5:
6: public void connect() {
7: System.out.println("Connecting to the Internet ...");
8: System.out.println("Using a " + method);
9: }
10: }


If there were no errors, you now have three class files: Modem.class, CableModem.class, and DslModem.class. However, you cannot run any of these class files because they do not have main() blocks like the ones in other programs you’ve created. You need to create a short application to test out the class hierarchy you have just built.

Return to NetBeans and create a new Empty Java File with the class name ModemTester. Enter Listing 10.5 in the source editor and save the file.

LISTING 10.5 The Full Text of ModemTester.java


1: package com.java24hours;
2:
3: public class ModemTester {
4: public static void main(String[] arguments) {
5: CableModem surfBoard = new CableModem();
6: DslModem gateway = new DslModem();
7: surfBoard.speed = 500000;
8: gateway.speed = 400000;
9: System.out.println("Trying the cable modem:");
10: surfBoard.displaySpeed();
11: surfBoard.connect();
12: System.out.println("Trying the DSL modem:");
13: gateway.displaySpeed();
14: gateway.connect();
15: }
16: }


When you run the program, you should see output matching Figure 10.4.

Image

FIGURE 10.4 The output of the ModemTester program.

The following things are taking place in Listing 10.5:

Image Lines 5–6—Two new objects are created: a CableModem object called surfBoard and a DslModem object called gateway.

Image Line 7—The speed variable of the CableModem object named surfBoard is set to 500000.

Image Line 8—The speed variable of the DslModem object named gateway is set to 400000.

Image Line 10—The displaySpeed() method of the surfBoard object is called. This method is inherited from Modem—even though it isn’t present in the CableModem class, you can call it.

Image Line 11—The connect() method of the surfBoard object is called.

Image Line 12—The displaySpeed() method of the gateway object is called.

Image Line 13—The connect() method of the gateway object is called.

Summary

After creating your first class of objects and arranging several classes into a hierarchy, you ought to be more comfortable with the term object-oriented programming (OOP). You learn more about object behavior and attributes in the next two hours as you start creating more sophisticated objects.

Terms such as program, class, and object make more sense as you become more experienced with this style of development. OOP is a concept that takes some time to get used to. When you have mastered it, you find that it’s an effective way to design, develop, and debug computer programs.

Workshop

Q&A

Q. Can classes inherit from more than one class?

A. It’s possible with some programming languages (such as C++), but not Java. Multiple inheritance is a powerful feature, but it also makes OOP a bit harder to learn and use. Java’s developers decided to limit inheritance to one superclass for any class, although a class can have numerous subclasses. One way to compensate for this limitation is to inherit methods from a special type of class called an interface. You learn more about interfaces during Hour 19, “Creating a Threaded Program.”

Q. When would you want to create a method that isn’t public?

A. The main time you would not want to make a method available to other programs is when the method is strictly for the use of one program you’re writing. If you’re creating a game program and your shootRayGun() method is highly specific to the game you’re writing, it could be a private method. To keep a method from being public, leave off the public statement in front of the method’s name.

Q. Why is it possible to use char values as if they were int values?

A. A character can be used as an int variable because each character has a corresponding numeric code that represents its position in the character set. If you have a variable named k with the value 67, the cast (char) k produces the character value ‘C’ because the numeric code associated with a capital C is 67, according to the ASCII character set. The ASCII character set is part of the Unicode character standard adopted by the Java language.

Q. Does Tabasco hot sauce spoil?

A. No, it doesn’t, although if you keep an opened bottle around for several years it will change color. The ingredients of vinegar, red pepper, and salt are an extremely inhospitable environment for bacterial growth.

McIlhenny Company, the maker of Tabasco, says the original brand has a shelf life of five years. Other versions have a shelf life from 18 months to three years.

As a huge fan of the product, I find it hard to believe anyone is keeping a bottle of Tabasco around long enough to ask this question.

Quiz

The following questions test your knowledge of objects and the programs that use them.

1. What statement is used to enable one class to inherit from another class?

A. inherits

B. extends

C. handItOverAndNobodyGetsHurt

2. Why are compiled Java programs saved with the .class file extension?

A. Java’s developers think it’s a classy language.

B. It’s a subtle tribute to the world’s teachers.

C. Every Java program is a class.

3. What are the two things that make up an object?

A. Attributes and behavior

B. Commands and data files

C. Spit and vinegar

Answers

1. B. The extends statement is used because the subclass is an extension of the attributes and behavior of the superclass and of any superclasses above that in the class hierarchy.

2. C. Your programs are always made up of at least one main class and any other classes that are needed.

3. A. In a way, B also is true because commands are comparable to behavior, and data files are analogous to attributes.

Activities

If you don’t object, you can extends your knowledge of this hour’s topics with the following activities:

Image Create an AcousticModem class with a speed of 300 and its own connect() method.

Image Add a disconnect() method to one of the classes in the Modem project, deciding where it should go to support modem disconnection in cable, DSL, and acoustic modems.

To see Java programs that implement these activities, visit the book’s website at www.java24hours.com.