Objects and Classes

Object-Oriented (OO) concepts of modularity, abstraction, composition, and hierarchy are very powerful and require intense attention to detail. This chapter gives a detailed presentation of OO as implemented by Java. The terminology in this article is a little different; name-binding is called name-scope. The chapter begins with an explanation of the data and procedures of a class (called class variables and class methods). The class data can be fixed for all objects, in which case, it is called static. Static variables are common to all objects. There is only one copy and, thus only one value, stored in the class.

A name (variable) is associated with a 'value'. A Java class can have any number of variables and each object (instance) of the class contains its own copy of those variables. In the terminology for Java, each object has a name, which is a pointer to the location of each instance of an class, and its variables. The next detail to note is how objects are created and initialized (i.e. values assigned to its instance variables and its methods names) by assigning values to them in the class via constructors. 

A consequence of the concepts of modularity and abstraction is reuse. In writing an OO program we can use classes that have been written by others and are part of the language or contained in class libraries associated with the language. Recall that the generic computing paradigm consists of several states: requirements, design, implementation, and validation. In software engineering, it is referred to as the programming process.

Section 5.3 gives insight into writing programs using classes. What classes, what objects, and how they are related are questions of program design. Section 5.4 illustrates the design and implementation stages of the process. The latter sections continue with the VERY important OO details of inheritance and polymorphism. They create a class hierarchy that enables code to be shared among classes and among similar, but different, objects. Whereas Java has simple inheritance (a subclass can extend one superclass), C++ has multiple inheritance ( a subclass can extend 2 or more superclasses). Java does, however, have a restricted kind of multiple inheritance called interfaces, where an interface can be implemented by 2 or more classes. As you read, think about how the concepts are connected. If you understand variable names, in particular the object names 'this' and 'super', the class name 'Object', and the dot naming convention (like ClassName.objectName.methodname), you should have a good understanding of the concepts and details presented in this article.


Objects, Instance Methods, and Instance Variables

Arrays and Objects

Arrays are objects. Like Strings they are special objects, with their own unique syntax. An array type such as int[] or String[] is actually a class, and arrays are created using a special version of the new operator. As in the case for other object variables, an array variable can never hold an actual array only a reference to an array object. The array object itself exists in the heap. It is possible for an array variable to hold the value null, which means there is no actual array.

For example, suppose that list is a variable of type int[]. If the value of list is null, then any attempt to access list.length or an array element list[i] would be an error and would cause an exception of type NullPointerException. If newlist is another variable of type int[], then the assignment statement

newlist = list;

only copies the reference value in list into newlist. If list is null, the result is that newlist will also be null. If list points to an array, the assignment statement does not make a copy of the array. It just sets newlist to refer to the same array as list. For example, the output of the following code segment

list = new int[3];
list[1] = 17;
newlist = list; // newlist points to the same array as list!
newlist[1] = 42;
System.out.println( list[1] );

would be 42, not 17, since list[1] and newlist[1] are just different names for the same element in the array. All this is very natural, once you understand that arrays are objects and array variables hold pointers to arrays.

This fact also comes into play when an array is passed as a parameter to a subroutine. The value that is copied into the subroutine is a pointer to the array. The array is not copied. Since the subroutine has a reference to the original array, any changes that it makes to elements of the array are being made to the original and will persist after the subroutine returns.

Arrays are objects. They can also hold objects. The base type of an array can be a class. We have already seen this when we used arrays of type String[], but any class can be used as the base type. For example, suppose Student is the class defined earlier in this section. Then we can have arrays of type Student[]. For an array of type Student[], each element of the array is a variable of type Student. To store information about 30 students, we could use an array

Student[] classlist; // Declare a variable of type Student[].
classlist = new Student[30]; // The variable now points to an array.

The array has 30 elements, classlist[0], classlist[1], ... classlist[29]. When the array is created, it is filled with the default initial value, which for an object type is null. So, although we have 30 array elements of type Student, we don't yet have any actual Student objects! All we have is 30 nulls. If we want student objects, we have to create them:

Student[] classlist;
classlist = new Student[30];
for ( int i = 0; i < 30; i++ ) {
 classlist[i] = new Student();
}

Once we have done this, each classlist[i] points to an object of type Student. If we want to talk about the name of student number 3, we can use classlist[3].name. The average for student number i can be computed by calling classlist[i].getAverage(). You can do anything with classlist[i] that you could do with any other variable of type Student.