As you saw in Chapter 1, a class is a prescription for a particular kind of object - it defines a new type. We can use the class definition to create objects of that class type, that is, to create objects that incorporate all the components specified as belonging to that class.
In case that's too abstract, look back to the last chapter, where we used the String class. This is a comprehensive definition for a string object, with all the operations you are likely to need built in. This makes String objects indispensable and string handling within a program easy.
The String class lies towards one end of a spectrum in terms of complexity in a class. The String class is intended to be usable in any program. It includes facilities and capabilities for operating on String objects to cover virtually all circumstances in which you are likely to use strings. In most cases your own classes won't need to be this elaborate. You will typically be defining a class to suit your particular application. A very simple class for instance, a Plane or a Person, may well represent objects that can potentially be very complicated, if that fulfils your needs. A Person object might just contain a name, address, and phone number for example if you are just implementing an address book. In another context, in a payroll program perhaps, you might need to represent a Person with a whole host of properties, such as age, marital status, length of service, job code, pay rate, and so on. It all depends on what you intend to do with objects of your class.
In essence a class definition is very simple. There are just two kinds of things that you can include in a class definition:
These are variables that store data items that typically differentiate one object of the class from another. They are also referred to as data members of a class.
These define the operations you can perform for the class - so they determine what you can do to, or with, objects of the class. Methods typically operate on the fields - the variables of the class.
The fields in a class definition can be of any of the basic types, or they can be references to objects of any class type, including the one that you are defining.
The methods in a class definition are named, self-contained blocks of code that typically operate on the variables that appear in the class definition. Note though, that this doesn't necessarily have to be the case, as you might have guessed from the main() methods we have written in all our examples up to now.
An object of a class is also referred to as an instance of that class. When you create an object, the object will contain all the variables that were included in the class definition. However, the variables in a class definition are not all the same - there are two kinds.
One kind of variable in a class is associated with each object uniquely - each instance of the class will have its own copy of each of these variables, with its own value assigned. These differentiate one object from another, giving an object its individuality - the particular name, address, and telephone number in a given Person object for instance. These are referred to as instance variables.
The other kind of class variable is associated with the class, and is shared by all objects of the class. There is only one copy of each of these kinds of variables no matter how many class objects are created, and they exist even if no objects of the class have been created. This kind of variable is referred to as a class variable because the variable belongs to the class, not to any particular object, although as we have said, all objects of the class will share it. These variables are also referred to as static fields because, as we will see, you use the keyword static when you declare them.
Because this is extremely important to understand, let's summarize the two kinds of variables that you can include in your classes:
Each object of the class will have its own copy of each of the instance variables that appear in the class definition. Each object will have its own values for each instance variable. The name 'instance variable' originates from the fact that an object is an 'instance' or an occurrence of a class and the values stored in the instance variables for the object differentiate the object from others of the same class type. An instance variable is declared within the class definition in the usual way, with a type name and a variable name, and can have an initial value specified.
A given class will only have one copy of each of its class variables, and these will be shared between all the objects of the class. The class variables exist even if no objects of the class have been created. They belong to the class, and they can be referenced by any object or class, not just instances of that class. If the value of a class variable is changed, the new value is available in all the objects of the class. This is quite different from instance variables where changing a value for one object does not affect the values in other objects. A class variable must be declared using the keyword static preceding the type name.
Look at the following diagram, which illustrates the difference between the two:
This shows a schematic of a class Sphere with one class variable PI, and four instance variables, radius, xCenter, yCenter, and zCenter. Each of the objects, globe and ball, will have their own variables, radius, xCenter, yCenter, and zCenter, but both will share a single copy of the class variable PI.
Why would you need two kinds of variables in a class definition? The instance variables are clearly necessary since they are the parameters that distinguish a particular object. The radius and the coordinates of the center of the sphere are fundamental to determining how big a particular Sphere object is, and where it is in space. However, although the variable PI is a fundamental parameter for a sphere - to calculate the volume for example - it would be wasteful to store a value for PI in every object, since it is always the same. Incidentally, it is also available from the standard class Math so it is somewhat superfluous in this case, but you get the general idea. So one use for class variables is to hold constant values such as ( that are common to all objects of the class.
Another use for class variables is to track data values that are common to all objects of a class, and that need to be available even when no objects have been defined. For example, if you wanted to keep a count of how many objects of a class have been created in your program, you would define the variable storing the count as a class variable. It would be essential to use a class variable, because you would still want to be able to use your count variable even when no objects have been declared.
The methods that you define for a class provide the actions that can be carried out using the variables specified in the class definition.
Analogous to the variables in a class definition, there are two varieties of methods - instance methods and class methods. You can execute class methods even when no objects of a class exist, whereas instance methods can only be executed in relation to a particular object, so if no objects exist, there are no instance methods to be executed. Again, like class variables, class methods are declared using the keyword static so they are sometimes referred to as static methods. We saw in the previous chapter that the valueOf() method is a static member of the String class.
Since class methods can be executed when there are no objects in existence, they cannot refer to instance variables. This is quite sensible if you think about it - trying to operate with variables that might not exist is bound to cause trouble. In fact the Java compiler won't let you try. If you reference an instance variable in the code for a class method, it won't compile - you'll just get an error message. The method main(), where execution of a Java application starts, must always be declared as static, as you have seen. The reason for this should be apparent by now. Before an application starts execution, no objects exist, so in order to start execution, you need a method that is executable even though there are no objects - a static method therefore.
The class Sphere might well have an instance method volume() to calculate the volume of a particular object. It might also have a class method objectCount() to return the current count of how many objects of type Sphere have been created. If no objects exist, you could still call this method and get the count 0.
Note that, although instance methods are specific to objects of a class, there is only ever one copy of an instance method in memory that is shared by all objects of the class, as it would be extremely expensive to replicate all the instance methods for each object. There is a special mechanism that ensures that, each time you call a method the codes executes in a manner that is specific to an object, but we will defer exploring this until a little later in this chapter.
Apart from making the method main(), perhaps the most common use for class methods is when a class is just used to contain a bunch of utility methods, rather than as a specification for objects. All executable code in Java has to be within a class, but there are lots of general-purpose functions that you need that don't necessarily have an object association - calculating a square root, for instance, or generating a random number. For example, the mathematical functions that are implemented as class methods in the standard class Math, don't relate to class objects at all - they operate on values of the basic types. You don't need objects of type Math, you just want to use the methods from time to time, and you can do this as we saw in Chapter 2. The class Math also contains some class variables containing useful mathematical constants such as e and p.
You will often want to access variables and methods, defined within a class, from outside it. We will see later that it is possible to declare class members with restrictions on accessing them from outside, but let's cover the principles that apply where the members are accessible. We need to consider accessing static members and instance members separately.
You can access a static member of a class using the class name, followed by a period, followed by the member name. With a class method you will also need to supply the parentheses enclosing any arguments to the method after the method name. The period here is called the dot operator. So, if you wanted to calculate the square root of p you could access the class method sqrt() and the class variable PI that are defined in the Math class as follows:
double rootPi = Math.sqrt(Math.PI);
This shows how you call a static method - you just prefix it with the class name and put the dot operator between them. We also reference the static data member, PI, in the same way - as Math.PI. If you have a reference to an object of a class type available, then you can also use that to access a static member of a class method. You just use the variable name, followed by the dot operator, followed by the member name.
Instance variables and methods can only be called using an object reference, as by definition they relate to a particular object. The syntax is exactly the same as we have outlined for static members. You put the name of the variable referencing the object followed by a period, followed by the member name. To use a method volume() that has been declared as an instance method in the Sphere class, you might write:
double ballVolume = ball.volume();
Here the variable ball is of type Sphere and it contains a reference to an object of this type. We call its volume() method that calculates the volume of the ball object, and the result that is returned is stored in the variable, ballVolume.