6.1 Creating Objects

     In mathematics, a fraction can be defined as an expression of the form together with rules about how we perform operations such as addition and multiplication on such expressions. Examples of fractions are expressions like , or In the first case, we are thinking of the class of all fractions; in the second we are thinking of particular instances of that class. In Java, to help us manipulate things like fractions (along with much more complex things), we can construct classes that define the way that things look and behave along with objects that give us instances of those classes.

     As an example of these classes and objects, let us look at how we might introduce the concept of a fraction into Java. Ignoring, for the moment, the operations that can be performed on fractions, we can consider a fraction to be composed of two parts: a numerator and a denominator. If we want the numerator and denominator of our fractions to both be of type int, we can define the class of fractions as follows:

     class Fraction
     {
          int num;
          int den;
     }

This class is very different from the ones that we have seen up to this point in our study of Java. It does not have a main method; in fact, it has no methods at all! It simply defines what something called a Fraction should look like: something that has two int parts that we have called a num and a den. We call these parts fields of the class. A field is declared outside a method while a local variable is declared inside a method.' We can illustrate the structure of the class with a diagram, as follows:

We should warn you that, although we think that this distinction between fields and local variables is a useful one, not everybody uses these terms. We can think of the Fraction class as a model, blueprint, or template of what a fraction should look like. All fractions have both a numerator and a denominator. The class definition makes this idea explicit; it defines a new type called Fraction that we can use in our programs. The definition does not actually create any fractions; it simply shows us what any fractions that we eventually create will look like. When we do create any fractions, each one of them will have its own num and den fields. Since each instance of a fraction will have these fields, they are, reasonably enough, called instance fields. In a program that uses fractions, this class can appear separately from the class that contains the main method. Once we have defined what we mean by a fraction, we can then create actual fractions, using our template. To begin to do this, we can, in the main method of our program, say, make the declaration:

Fraction f;

This creates a variable f that can act as a reference to a fraction. Since we have not assigned f a value, it does not at this point actually refer to a fraction. To achieve this, we can now write:

f = new Fraction();

This causes Java to create an object, an instance of the type Fraction. In addition a reference to the location in memory of the newly created object is stored in the variable f. Pictorially, we can illustrate what we have created as follows:

Notice in the preceding diagram that the num and den fields are both shown with the value zero. Although Java does not initialize local variables when we declare them, it does initialize all numeric fields to the value zero when we create an object containing those fields. We can (and usually will) combine the process of declaring and creating a new Fraction object f by writing

Fraction f = new Fraction();

If we wanted our object to represent the fraction rather than , we could now make the following assignment statements:

     f.num = 2;
     f.den = 3;

You might find it useful to read these assignment statements as

     f's num = 2;
     f’s den = 3;

Pictorially, the result of the assignments is:

Using the same template, we can create as many objects of that type as we wish.

Example 1

To create two fractions, f1 and f2, representing the fractions and , we could write: Fraction f1 = new Fraction(); f1.num = 3; f1.den = 4; Fraction f2 = new Fraction(); f2.num 5; f2.den = 6; Pictorially, the result of all of this would be:

Once we have created objects, we can manipulate their fields in the same ways that we do with local variables.

Example 2

Suppose that f1 and f2 have been created as shown in the previous example. If we were to write      f1.num-- ;      f1.den = f2.den + 3; then f1 would represent the fraction and f2 would be unchanged.

As we have already noted, if we simply declare a reference variable, that variable does not yet actually refer to an object. For example, if we were to write Fraction £1; the result is an uninitialized Fraction variable. An attempt to use £1 in this state will result in an error during compilation of the program. To avoid such compilation errors, we can initialize a reference variable so that it does not refer to an object (but is still defined) by assigning it the value null. If we write Fraction f2 = null; then we can print f2 (producing the output "null") or compare f2 to other objects (an idea that we will explore in more detail later). The variables £1 and f2 are illustrated in the next diagram. The dot inside f1 indicates that it has no value. We show the null reference of f2 with the symbol used to indicate a ground in a diagram of an electrical circuit.

As we have already seen with strings, objects are very different from primitive types so, when we attempt to apply operations to objects, we must be very careful of what we are doing. Otherwise, the results can be something quite different from what we want. The next example examines the meaning of assignment with objects.

Example 3

Suppose that we have created an object f of our Fraction class by writing Fraction f = new Fraction(); f.num = 5; f.den = 8; to obtain the object shown in the next diagram.

If we now write Fraction g = f; the result is the usual one produced by an assignment: a value in one memory location is copied into another memory location. Here, however, the copying is done from the reference f to the reference g, producing the result shown in the next diagram where f and g, since they have the same value, both refer to the same object.

If we were now to write
     g.num = 1;
this would change the num field of the object to which g refers. Since f refers to the same object, f would now represent the fraction . We say that g is an alias of f.

Exercise 6.1

  1. What is the essential difference between a local variable and a field?
  2. Write statements that could be used to create an object of type Fraction representing the fraction
  3. Assuming that the class Fraction is defined as it was in the text, state the error in the following fragment.

         Fraction p;
         p.num 7;
         p.den = 8;

  4. Draw diagrams like those shown in the text to illustrate the results of the given fragment.

         Fraction p, q, r;
         p = new Fraction();
         q = new Fraction();
         r = q;
         p.num = p.den = 2;
         q.num = 2*p.den;
         p.den++;
         --p.num;
         r.den = p.num + 2;

  5. Assuming that two objects £1 and f2 of type Fraction have been created and assigned values, write statements to perform each task.

         (a) Double the value of f1.
         (b) Invert f2.
         (c) Make £1 equal to the (unsimplified) product of f1 and f2.
         (d) Make f2 equal to the (unsimplified) sum of f 1 and f2.
         (e) Make f1 equal to 1£11.

  6. A circle in the Cartesian plane can be described uniquely by its centre and its radius. Thus, a class called Circle that could be used to represent such circles might start with the following:

         class Circle
         {
              double x;           // x-coordinate of centre
              double y;           // y-coordinate of centre
              double r;           // radius
         }

    An object of this class, representing a circle with centre at (5,2) and having radius 3 is shown in the next diagram.

    Using this class, write a Java program that performs the following actions.

         (a) Create Circle objects cl and c2 where cl represents a circle with centre at (1,2) having radius 4 while c2 represents a circle with centre at (-2,0) having radius 2.
         (b) Set the double variable distance to the distance from the origin to the centre of c1 and then print this value.
         (c) Set the double variable centreSeparation equal to the distance between the centres of cl and c2 and then print this value.
         (d) Set the double variable minDistance to the minimum distancefrom a point on c1 to a point on c2 and then print this value.

  7. A complex number z = a +bi can be specified by its real part, a, and its imaginary part, b.

         (a) Create a class Complex that could be used to represent complex numbers.
         (b) Create objects z1 and z2 that represent the complex numbers 2 + 3i and 5 - 4i.
         (c) Write a fragment that assigns to zl the sum of zl and z2.