Describing What Your Object Is Like - 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 11. Describing What Your Object Is Like

THIS HOUR’S TO-DO LIST:

Image Create variables for an object or class.

Image Use methods with objects and classes.

Image Call a method and return a value.

Image Create a constructor.

Image Send arguments to a method.

Image Use this to refer to an object.

Image Create new objects.

As you learned during the past hour’s introduction to object-oriented programming (OOP), an object is a way of organizing a program so it has everything it needs to accomplish a task. Objects consist of attributes and behavior.

Attributes are the information stored within an object. They can be variables such as integers, characters, and Boolean values, or objects such as String and Calendar objects. Behavior is the groups of statements used to handle specific jobs within the object. Each of these groups is called a method.

Up to this point, you have been working with methods and variables of objects without knowing it. Any time your statement had a period in it that wasn’t a decimal point or part of a string, an object was involved.

Creating Variables

In this hour, you are looking at a sample class of objects called Virus whose sole purpose in life is to reproduce in as many places as possible—much like some people I knew in college. A Virus has several different things it needs to do its work, and these are implemented as the behavior of the class. The information that’s needed for the methods are stored as attributes.

The attributes of an object represent variables needed for the object to function. These variables could be simple data types such as integers, characters, and floating-point numbers, or they could be arrays or objects of classes such as String or Calendar. You can use an object’s variables throughout its class, in any of the methods the object contains. By convention, you create variables immediately after the class statement that creates the class and before any methods.

One of the things that a Virus object needs is a way to indicate that a file already has been infected. Some computer viruses change the field that stores the time a file was last modified; for example, a virus might move the time from 7:41:20 to 7:41:61. Because no normal file would be saved on the 61st second of a minute, the time signifies that the file was infected.

The Virus object uses the impossible seconds value 86 in an integer variable called newSeconds. The following statements begin a class called Virus with an attribute called newSeconds and two other attributes:

public class Virus {
public int newSeconds = 86;
public String author = "Sam Snett";
int maxFileSize = 30000;
}

All three variables are attributes for the class: newSeconds, maxFileSize, and author.

Putting a statement such as public in a variable declaration statement is called access control because it determines how other objects made from other classes can use that variable—or if they can use it at all.

Making a variable public makes it possible to modify the variable from another program that is using the Virus object.

If the other program attaches special significance to the number 92, for instance, it can change newSeconds to that value. The following statements create a Virus object called influenza and set its newSeconds variable:

Virus influenza = new Virus();
influenza.newSeconds = 92;

In the Virus class, the author variable also is public, so it can be changed freely from other programs. The other variable, maxFileSize, only can be used within the class itself.

When you make a variable in a class public, the class loses control over how that variable is used by other programs. In many cases, this might not be a problem. For example, the author variable can be changed to any name or pseudonym that identifies the author of the virus. The name might eventually be used on court documents if the author is prosecuted, so you don’t want to pick a dumb one. The State of Ohio v. LoveHandles doesn’t have the same ring to it as Ohio v. MafiaBoy.

Restricting access to a variable keeps errors from occurring if the variable is set incorrectly by another program. With the Virus class, if newSeconds is set to a value of 60 or less, it isn’t reliable as a way to tell that a file is infected. Some files might be saved with that number of seconds regardless of the virus. If the Virus class of objects needs to guard against this problem, you need to do these two things:

Image Switch the variable from public to protected or private, two other statements that provide more restrictive access.

Image Add behavior to change the value of the variable and report the value of the variable to other programs.

You can use a protected variable only in the same class as the variable, any subclasses of that class, or by classes in the same package. A package is a group of related classes that serve a common purpose. An example is the java.util package, which contains classes that offer useful utilities such as date and time programming and file archiving. When you use the import statement in a Java program with an asterisk, as in import java.util.*, you are making it easier to refer to the classes of that package in a program.

A private variable is restricted even further than a protected variable—you can use it only in the same class. Unless you know that a variable can be changed to anything without affecting how its class functions, you should make the variable private or protected.

The following statement makes newSeconds a private variable:

private int newSeconds = 86;

If you want other programs to use the newSeconds variable in some way, you have to create behavior that makes it possible. This task is covered later in the hour.

There also is another type of access control: the lack of any public, private, or protected statement when the variable is created.

In most of the programs you have developed prior to this hour, you didn’t specify any access control. When no access control is set, the variable is available only to classes in the same package. This is called default or package access.

Creating Class Variables

When you create an object, it has its own version of all variables that are part of the object’s class. Each object created from the Virus class of objects has its own version of the newSeconds, maxFileSize, and author variables. If you modified one of these variables in an object, it would not affect the same variable in another Virus object.

There are times when an attribute should describe an entire class of objects instead of a specific object itself. These are called class variables. If you want to keep track of how many Virus objects are being used in a program, you could use a class variable to store this information. Only one copy of the variable exists for the whole class. The variables you have been creating for objects thus far can be called object variables because they are associated with a specific object.

Both types of variables are created and used in the same way, but static is part of the statement that creates class variables. The following statement creates a class variable for the Virus example:

static int virusCount = 0;

Changing the value of a class variable is no different than changing an object’s variables. If you have a Virus object called tuberculosis, you could change the class variable virusCount with the following statement:

tuberculosis.virusCount++;

Because class variables apply to an entire class, you also can use the name of the class instead:

Virus.virusCount++;

Both statements accomplish the same thing, but an advantage to using the name of the class when working with class variables is that it shows immediately that virusCount is a class variable instead of an object variable. If you always use object names when working with class variables, you aren’t able to tell whether they are class or object variables without looking carefully at the source code.


Caution

Although class variables are useful, you must take care not to overuse them. These variables exist for as long as the class is running. If a large array of objects is stored in class variables, it will take up a sizeable chunk of memory and never release it.


Class variables also are called static variables.

Creating Behavior with Methods

Attributes are the way to keep track of information about a class of objects, but for a class to do the things it was created to do, you must create behavior. Behavior describes the parts of a class that accomplish specific tasks. Each of these sections is called a method.


Note

The System.out.println() method might seem confusing because it has two periods instead of one. This is because two classes are involved in the statement: the System class and the PrintStream class. The System class has a variable called out that is aPrintStream object. println() is a method of the PrintStream class. The System.out.println() statement means, in effect, “Use the println() method of the out instance variable of the System class.” You can chain together references in this way.


You have been using methods throughout your programs up to this point without knowing it, including one in particular: println(). This method displays text onscreen. Like variables, methods are used in connection with an object or a class. The name of the object or class is followed by a period and the name of the method, as in object2.move() or Integer.parseInt().

Declaring a Method

You create methods with a statement that looks similar to the statement that begins a class. Both can take arguments between parentheses after their names, and both use { and } marks at the beginning and end. The difference is that methods can send back a value after they are handled. The value can be one of the simple types such as integers or Boolean values, or it can be a class of objects.

The following is an example of a method the Virus class can use to infect files:

public boolean infectFile(String filename) {
boolean success = false;
// file-infecting statements go here
return success;
}

This method takes a single argument: a string variable called filename, which is a variable that represents the file that should be attacked. If the infection is a success, the success variable is set to true.

In the statement that begins the method, boolean precedes the name of the method, infectFile. This statement signifies that a Boolean value is sent back after the method is handled. The return statement is what actually sends a value back. In this method, the value of success is returned.

If a method should not return a value, use the keyword void.

When a method returns a value, you can use the method as part of an expression. For example, if you created a Virus object called malaria, you could use statements such as these:

if (malaria.infectFile(currentFile)) {
System.out.println(currentFile + " has been infected!");
} else {
System.out.println("Curses! Foiled again!");
}

You can use a method that returns a value at any place in the program where you could have used a variable.

Earlier in the hour, you switched the newSeconds variable to private to prevent it from being read or modified by other programs.

When an instance variable is private, there’s still a way to make it possible for newSeconds to be used elsewhere: Create public methods in the Virus class that get the value of newSeconds and set newSeconds to a new value. These new methods should be public, unlike thenewSeconds variable itself, so they can be called in other programs.

Consider the following two methods:

public int getSeconds() {
return newSeconds;
}

public void setSeconds(int newValue) {
if (newValue > 60) {
newSeconds = newValue;
}
}

These methods are called accessor methods because they enable the newSeconds variable to be accessed from other objects.

The getSeconds() method is used to retrieve the current value of newSeconds. The getSeconds() method does not have any arguments, but it still must have parentheses after the method name. The setSeconds() method takes one argument, an integer called newValue. This argument is the new value of newSeconds. If newValue is greater than 60, the change will be made.

In this example, the Virus class controls how the newSeconds variable can be used by other classes. This process is called encapsulation, and it’s a fundamental concept of OOP. The better your objects are able to protect themselves against misuse, the more useful they are when you put them to work in other programs.

Although newSeconds is private, the new methods getSeconds() and setSeconds() are able to work with newSeconds because they are in the same class.

Similar Methods with Different Arguments

As you have seen with the setSeconds() method, you can send arguments to a method to affect what it does. Different methods in a class can have different names, but methods also can have the same name if they have different arguments.

Two methods can have the same name if they have a different number of arguments or the arguments are of different variable types. For example, it might be useful for the Virus class of objects to have two tauntUser() methods. One could have no arguments and would deliver a generic taunt. The other could specify the taunt as a string argument. The following statements implement these methods:

void tauntUser() {
System.out.println("That has gotta hurt!");
}

void tauntUser(String taunt) {
System.out.println(taunt);
}

The methods have the same name, but the arguments differ: one has no argument, the other has a single String argument. The arguments to a method are called the method’s signature. A class can have different methods with the same name as long as each method has a different signature.

Constructor Methods

When you want to create an object in a program, the new statement is used, as in the following example:

Virus typhoid = new Virus();

This statement creates a new Virus object called typhoid. When you use the new statement, a special method of that object’s class is called. This method is called a constructor because it handles the work required to create the object. The purpose of a constructor is to set up any variables and call the methods that must take place for the object to function properly.

Constructors are defined like other methods, except they cannot return a value. The following are two constructors for the Virus class of objects:

public Virus() {
author = "Ignoto"; // author is a string
maxFileSize = 30000; // maxFileSize is an int
}

public Virus(String name, int size) {
author = name;
maxFileSize = size;
}

Like other methods, constructors can use the arguments they are sent as a way to define more than one constructor in a class. In this example, the first constructor would be called when a new statement such as the following is used:

Virus mumps = new Virus();

The other constructor could be called only if a string and an integer are sent as arguments with the new statement, as in this example:

Virus rubella = new Virus("April Mayhem", 60000);

If you don’t include any constructor methods in a class, it inherits a single constructor with no arguments from its superclass. There also might be other constructors that it inherits, depending on the superclass used.


Caution

If your subclass defines a constructor with one or more arguments, the class will no longer inherit a constructor with no arguments from its superclass. For this reason, you must always define a no-argument constructor when your class has other constructors.


In any class, there must be a constructor that has the same number and type of arguments as the new statement that’s used to create objects of that class. In the example of the Virus class, which has Virus() and Virus(String name, int size) constructors, you only could createVirus objects with two different types of new statements: one without arguments and one with a string and an integer as the only two arguments.

Class Methods

Like class variables, class methods are a way to provide functionality associated with an entire class instead of a specific object. Use a class method when the method does nothing that affects an individual object of the class. In the previous hour, “Creating Your First Object,” you used theparseInt() method of the Integer class to convert a string to a variable of the type int:

int fontSize = Integer.parseInt(fontText);

This is a class method. To make a method into a class method, use static in front of the method name, as in the following code:

static void showVirusCount() {
System.out.println("There are " + virusCount + " viruses");
}

The virusCount class variable was used earlier to keep track of how many Virus objects have been created by a program. The showVirusCount() method is a class method that displays this total, and you can call it with a statement such as the following:

Virus.showVirusCount();

Variable Scope Within Methods

When you create a variable or an object inside a method in one of your classes, it is usable only inside that method. The reason for this is the concept of variable scope. Scope is the block in which a variable exists in a program. If you go outside of the part of the program defined by the scope, you can no longer use the variable.

The { and } brackets in a program define the boundaries for a variable’s scope. Any variable created within these marks cannot be used outside of them. For example, consider the following statements:

if (numFiles < 1) {
String warning = "No files remaining.";
}
System.out.println(warning);

This code does not work—and does not compile in NetBeans—because the warning variable was created inside the brackets of the if block.

Those brackets define the scope of the variable. The warning variable does not exist outside of the brackets, so the System.out.println() method cannot use it as an argument.

When you use a set of brackets inside another set of brackets, you need to pay attention to the scope of the enclosed variables. Take a look at the following example:

if (infectedFiles < 5) {
int status = 1;
if (infectedFiles < 1) {
boolean firstVirus = true;
status = 0;
} else {
firstVirus = false;
}
}

See any problems? In this example the status variable can be used anywhere, but the statement that assigns a value of false to the firstVirus variable causes a compiler error. Because firstVirus is created within the scope of the if (infectedFiles < 1) statement, it doesn’t exist inside the scope of the else statement that follows.

To fix the problem, firstVirus must be created outside both of these blocks so that its scope includes both of them. One solution is to create firstVirus one line after status is created.

Rules that enforce scope make programs easier to debug because scope limits the area in which you can use a variable. This reduces one of the most common errors that can crop up in programming: using the same variable two different ways in different parts of a program.

The concept of scope also applies to methods because they are defined by an opening bracket and closing bracket. A variable created inside a method cannot be used in other methods. You only can use a variable in more than one method if it was created as an object variable or class variable.

Putting One Class Inside Another

Although a Java program is called a class, there are many occasions when a program requires more than one class to get its work done. These programs consist of a main class and any helper classes that are needed.

When you divide a program into multiple classes, there are two ways to define the helper classes. One way is to define each class separately, as in the following example:

public class Wrecker {
String author = "Ignoto";

public void infectFile() {
VirusCode vic = new VirusCode(1024);
}
}

class VirusCode {
int vSize;

VirusCode(int size) {
vSize = size;
}
}

In this example, the VirusCode class is a helper class for the Wrecker class. Helper classes often are defined in the same source code file as the class they’re assisting. When the source file is compiled, multiple class files are produced. The preceding example produces the filesWrecker.class and VirusCode.class when compiled.


Caution

If more than one class is defined in the same source file, only one of the classes can be public. The other classes should not have public in their class statements. The name of the source code file must match the public class that it defines.


When creating a main class and a helper class, you also can put the helper inside the main class. When this is done, the helper class is called an inner class.

You place an inner class within the opening bracket and closing bracket of another class:

public class Wrecker {
String author = "Ignoto";

public void infectFile() {
VirusCode vic = new VirusCode(1024);
}

class VirusCode {
int vSize;

VirusCode(int size) {
vSize = size;
}
}
}

You can use an inner class in the same manner as any other kind of helper class. The main difference—other than its location—is what happens after the compiler gets through with these classes. Inner classes do not get the name indicated by their class statement. Instead, the compiler gives them a name that includes the name of the main class.


Note

Inner classes enable some complex programming techniques in Java that will make more sense after you have more experience with the language. Nine more hours, to be precise. This book gets back to the subject in Hour 20, “Using Inner Classes and Closures.”


In the preceding example, the compiler produces Wrecker.class and Wrecker$VirusCode.class.

Using the this Keyword

Because you can refer to variables and methods in other classes along with variables and methods in your own classes, the variable you’re referring to can become confusing in some circumstances. One way to make things more clear is with the this statement—a way to refer within a program to the program’s own object.

When you are using an object’s methods or variables, you put the name of the object in front of the method or variable name, separated by a period. Consider these examples:

Virus chickenpox = new Virus();
chickenpox.author = "LoveHandles";
chickenpox.setSeconds(75);

These statements create a new Virus object called chickenpox, set the name variable of chickenpox, and then call the setSeconds() method of chickenpox.

There are times in a program when you need to refer to the current object—in other words, the object represented by the program itself. For example, inside the Virus class, you might have a method that has its own variable called author:

public void checkAuthor() {
String author = null;
}

In this example, a variable called author exists within the scope of the checkAuthor() method, but it isn’t the same variable as an object variable called author. If you want to refer to the current object’s author variable, you have to use the this statement, as in the following:

System.out.println(this.author);

By using this, you make it clear to which variable or method you are referring. You can use this anywhere in a class that you would refer to an object by name. If you want to send the current object as an argument to a method, for example, you could use a statement such as the following:

verifyData(this);

In many cases, the this statement is not needed to make it clear that you’re referring to an object’s variables and methods. However, there’s no detriment to using this any time you want to be sure you’re referring to the right thing.

The this keyword comes in handy in a constructor when setting the value of an object’s instance variables. Consider a Virus object that has author and maxFileSize variables. This constructor sets them:

public Virus(String author, int maxFileSize) {
this.author = author;
this.maxFileSize = maxFileSize;
}

Using Class Methods and Variables

At the insistence of our attorney, this hour’s first project is not the creation of a working virus. Instead, you create a simple Virus object that can count the number of Virus objects that a program has created and report the total.

You know the drill: Choose File, New File in NetBeans and create a new Empty Java File called Virus. Enter Listing 11.1 in the source editor. Click Save.

LISTING 11.1 The Full Text of Virus.java


1: package com.java24hours;
2:
3: public class Virus {
4: static int virusCount = 0;
5:
6: public Virus() {
7: virusCount++;
8: }
9:
10: static int getVirusCount() {
11: return virusCount;
12: }
13: }


Save the file, which NetBeans compiles automatically. This class lacks a main() method and thus cannot be run directly. To test out this new Virus class, you need to create a second class that can create Virus objects.

The VirusLab class is a simple application that creates Virus objects and then counts the number of objects that have been created with the getVirusCount() class method of the Virus class.

Open a new file with NetBeans and enter Listing 11.2. Save the file as VirusLab.java when you’re done.

LISTING 11.2 The Full Text of VirusLab.java


1: package com.java24hours;
2:
3: public class VirusLab {
4: public static void main(String[] arguments) {
5: int numViruses = Integer.parseInt(arguments[0]);
6: if (numViruses > 0) {
7: Virus[] virii = new Virus[numViruses];
8: for (int i = 0; i < numViruses; i++) {
9: virii[i] = new Virus();
10: }
11: System.out.println("There are " + Virus.getVirusCount()
12: + " viruses.");
13: }
14: }
15: }


The VirusLab class is an application that takes one argument when you run it at the command line: the number of Virus objects to create. To specify the command-line argument in NetBeans, do the following:

1. Choose Run, Set Project Configuration, Customize. The Project Properties dialog opens.

2. Enter VirusLab in the Main Class field and enter the number of Virus objects you’d like the program to create in the Arguments field.

3. Click OK to close the dialog.

To run a program you’ve configured in this manner, choose Run, Run Main Project in NetBeans.

Arguments are read into an application using a string array that’s sent to the main() method. In the VirusLab class, this occurs in Line 4.

To work with an argument as an integer, the argument must be converted from a String object to an integer. This requires the use of the parseInt() class method of the Integer class. In Line 5, an int variable named numViruses is created from the first argument sent to the program on the command line.

If the numViruses variable is greater than 0, the following things take place in the VirusLab application:

Image Line 7—An array of Virus objects is created with the numViruses variable determining the number of objects in the array.

Image Lines 8–10—A for loop is used to call the constructor method for each Virus object in the array.

Image Lines 11–13—After all the Virus objects have been constructed, the getVirusCount() class method of the Virus class is used to count the number of its objects that have been created. This should match the argument that was set when you ran the VirusLab application.

If the numViruses variable is not greater than 0, nothing happens in the VirusLab application.

After the VirusLab.java file has been compiled, test it with any command-line argument you’d like to try. The number of Virus objects that can be created depends on the memory that’s available on your system when you run the VirusLab application. On the author’s system, anything greater than 128 million viruses causes the program to crash after displaying an OutOfMemoryError message.

If you don’t specify more Virus objects than your system can handle, the output should be something like Figure 11.1.

Image

FIGURE 11.1 The output of the VirusLab program.

Summary

You now have completed two of the three hours devoted to object-oriented concepts in this book. You’ve learned how to create an object, give behavior and attributes to the object and its class of objects, and convert objects and variables into other forms by using casting.

Thinking in terms of objects is one of the tougher challenges of the Java programming language. After you start to understand it, however, you realize that the entire language makes use of objects and classes.

During the next hour, you learn how to give your objects parents and children.

Workshop

Q&A

Q. Do you have to create an object to use class variables or methods?

A. No. Because class variables and methods aren’t associated with a specific object, you don’t need to create an object solely for the purpose of using them. The use of the Integer.parseInt() method is an example of this because you don’t have to create a new Integer object just to convert a string to an int value.

Q. Is there a list of all the built-in methods that Java supports?

A. Oracle offers full documentation for all classes in the Java language, including all public methods you can use, on the Web at http://download.java.net/jdk8/docs/api.

Q. Is there a way to control how much memory a Java program uses?

A. The memory available to the Java Virtual Machine when it runs an application is controlled by two things: the total physical memory available on the computer and the amount the JVM is configured to use. The default memory allocation is 256MB. A different amount can be set with the -Xmx command-line argument.

To set this in NetBeans, choose Run, Set Project Configuration, Customize. The Project Properties dialog opens with the Run settings at the front. In the VM Options field, enter -Xmx1024M to allocate 1024MB of memory to the JVM. Alter that number for more or less memory. Also fill out the Main Class and Arguments fields and run the program by choosing Run, Run Project.

Q. What do I have to do to be ranked in men’s tennis?

A. There are currently 2,136 male tennis players ranked in the ATP World Tour tennis rankings. If your goal is to do at least as well as the lowest ranked player, you must reach the round of 16 in an ITF Futures tournament.

At the time of this writing, Zach Itzstein is ranked in 2,136th place among men’s singles players. Itzstein achieved this distinction by earning only one point in the 15 tournaments he’s entered the past 52 weeks. Several hundred other players also have earned one point, but they did it in fewer tournaments.

Itzstein, a 25-year-old from Australia, played the Vietnam F1 futures tournament in March 2013. There was a 32-player qualifier and a 32-player field. Itzstein beat Kelsey Stevenson of Canada in two sets. He advanced to play Joshua Ward-Hibbert of England in the second round and lost in two sets. His year-to-date prize winnings are $3,448 (which also includes his doubles earnings, where he’s ranked 625th).

There’s probably a Futures tournament near you. More than 500 take place around the world each year. Visit www.itftennis.com for the calendar and entry information.

Good luck! If you reach the finals at Wimbledon, I want a seat in the players’ box.

Quiz

The following questions see if you have the attributes and behavior to understand OOP techniques.

1. In a Java class, a method is an example of what?

A. Attributes

B. Statements

C. Behavior

2. If you want to make a variable a class variable, what statement must you use when it is created?

A. new

B. public

C. static

3. What is the name for the part of a program in which a variable lives?

A. Its nest

B. The scope

C. Variable valley

Answers

1. C. A method is made up of statements, but it’s an example of behavior.

2. C. If the static statement is left off, the variable is an object variable instead of a class variable.

3. B. The compiler fails with an error when a variable is used outside of its scope.

Activities

If all this talk of viruses didn’t make you sick, you can increase your knowledge of this hour’s topics with the following activity:

Image Add a private variable to the Virus class that stores an integer called newSeconds. Create methods to return the value of newSeconds and change the value of newSeconds only if the new value is between 60 and 100.

Image Write a Java application that takes an argument as a string, converts it to a float variable, converts that to a Float object, and finally turns that into an int variable. Run it a few times with different arguments to see how the results change.

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