PART IV: Programming a Graphical User Interface
HOUR 13: Building a Simple User Interface
ptg7068951 One of the things that a Virusobject 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 13:41:20 to 13: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 Virusobject uses the impossible seconds value 86 in an integer vari- able called newSeconds.
The following statements begin a class called Viruswith an attribute called newSecondsand 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 publicin a variable declaration statement is called access controlbecause it determines how other objects made from other classes can use that variable—or if they can use it at all.
Making a variable publicmakes it possible to modify the variable from another program that is using the Virusobject.
If the other program attaches special significance to the number 92, for instance, it can change newSecondsto that value. The following statements create a Virusobject called influenzaand set its newSecondsvariable:
Virus influenza = new Virus();
influenza.newSeconds = 92;
In the Virusclass, the authorvariable also is public, so it can be changed freely from other programs. The other variable, maxFileSize, can be used only 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 authorvariable 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
ptg7068951
Creating Class Variables 139
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 Virusclass of objects needs to guard against this prob- lem, you need to do these two things:
. Switch the variable from publicto protectedor private, two other statements that provide more restrictive access.
. Add behavior to change the value of the variable and report the value of the variable to other programs.
You can use a protectedvariable only in the same class as the variable, any subclasses of that class, or classes in the same package. Apackageis a group of related classes that serve a common purpose. An example is the java.utilpackage, which contains classes that offer useful utilities such as date and time programming and file archiving. When you use the importstatement in a Java program with an asterisk, as in import java.util.*, you are making it easier to refer to the classes of that pack- age in a program.
Aprivatevariable is restricted even further than a protectedvariable—
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 privateor protected.
The following statement makes newSecondsa privatevariable:
private int newSeconds = 86;
If you want other programs to use the newSecondsvariable 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 protectedstatement when the variable is created.
In most of the programs you have created 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 Virusclass of objects
ptg7068951 has its own version of the newSeconds, maxFileSize, and authorvariables.
If you modified one of these variables in an object, it would not affect the same variable in another Virusobject.
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 Virusobjects 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 variablesbecause they are associated with a specific object.
Both types of variables are created and used in the same way, but staticis part of the statement that creates class variables. The following statement creates a class variable for the Virusexample:
static int virusCount = 0;
Changing the value of a class variable is no different than changing an object’s variables. If you have a Virusobject called tuberculosis, you could change the class variable virusCountwith 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 imme- diately that virusCountis 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.
Class variables also are called staticvariables.
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 behav- ior. Behavior describes the parts of a class that accomplish specific tasks.
Each of these sections is called a method.
CAUTION
Although class variables are useful, you must take care not to overuse them. These vari- ables 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 size- able chunk of memory and never release it.
ptg7068951
Creating Behavior with Methods 141
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 screen2D.drawString()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 val- ues, or it can be a class of objects.
The following is an example of a method the Virusclass 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 successvariable is set to true.
In the statement that begins the method, booleanprecedes the name of the method, infectFile. This statement signifies that a booleanvalue is sent back after the method is handled. The returnstatement is what actually sends a value back. In this method, the value of successis returned.
If a method should not return a value, use the keywordvoid.
When a method returns a value, you can use the method as part of an expression. For example, if you created a Virusobject 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!”);
}
NOTE
TheSystem.out.println() method might seem confusing because it has two periods instead of one. This is because two classes are involved in the statement—theSystemclass and the PrintStreamclass.
TheSystemclass has a variable calledoutthat is a
PrintStreamobject.println() is a method of the PrintStream class. The System.out.print- ln()statement means, in effect, “Use the println() method of the outvariable of theSystemclass.” You can chain together references in this way.
ptg7068951 You can use any method that returns a value at any place in the program
where you could use a variable.
Earlier in the hour, you switched the newSecondsvariable to privateto prevent it from being read or modified by other programs. There’s still a way to make it possible for newSecondsto be used elsewhere: Create publicmethods in the Virusclass that get the value of newSecondsand set newSecondsto a new value. These new methods should be public, unlike the newSecondsvariable 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 accessormethods because they enable the newSecondsvariable 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 newValueis greater than 60, the change will be made.
In this example, the Virusclass controls how the newSecondsvariable can be used by other classes. This process is called encapsulation, and it’s a fun- damental concept of OOP. The better your objects are able to protect them- selves against misuse, the more useful they are when you use them in other programs.
Though newSecondsis private, the new methods getSeconds()and setSeconds()are able to work with newSecondsbecause 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
ptg7068951
Creating Behavior with Methods 143
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 Virusclass 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 Stringargument. The arguments to a method are called the method’ssignature. A class can have different meth- ods 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 newstatement is used, as in the following example:
Virus typhoid = new Virus();
This statement creates a new Virusobject called typhoid. When you use the newstatement, a special method of that object’s class is called. This method is called a constructorbecause it handles the work required to cre- ate 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 Virusclass of objects:
public Virus() {
String author = “Ignoto”;
int maxFileSize = 30000;
}
public Virus(String name, int size) { author = name;
maxFileSize = size;
}
ptg7068951 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 newstatement such as the follow- ing 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 newstatement, 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 method with no arguments from its superclass. There also might be other constructor methods that it inherits, depending on the superclass used.
In any class, there must be a constructor method that has the same number and type of arguments as the newstatement that’s used to create objects of that class. In the example of the Virusclass, which has Virus()and Virus(String name, int size)constructors, you only could create Virus objects with two different types of newstatements: 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 associ- ated 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 the parseInt() method of the Integerclass 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 virusCountclass variable was used earlier to keep track of how many Virusobjects 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:
ptg7068951
Creating Behavior with Methods 145
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 con- cept of variable scope. Scope is the block in which a variable exists in a pro- gram. If you go outside of the part of the program defined by the scope, you can no longer use the variable.
The {and }statements 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 warningvariable was created inside the brackets of the ifblock. Those brackets define the scope of the variable. The warningvariable 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 fol- lowing 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 statusvariable can be used any- where, but the statement that assigns a value to the firstVirusvariable causes a compiler error. Because firstVirusis created within the scope of the if (infectedFiles < 1)statement, it doesn’t exist inside the scope of the elsestatement that follows.
To fix the problem, firstVirusmust be created outside both of these blocks so that its scope includes both of them. One solution is to create firstVirusone line after statusis created.
ptg7068951 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 pro- grams 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 VirusCodeclass is a helper class for the Wreckerclass.
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 files Wrecker.classand VirusCode.classwhen compiled.
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.
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 publicin their class statements. The name of the source code file must match the publicclass that it defines.
ptg7068951
Using the thisKeyword 147
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 classstatement. Instead, the compiler gives them a name that includes the name of the main class.
In the preceding example, the compiler produces Wrecker.classand 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 thisstatement—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.name = “LoveHandles”;
chickenpox.setSeconds(75);
These statements create a new Virusobject called chickenpox, set the namevariable of chickenpox, and then call the setSeconds()method of chickenpox.