Besides the primitive types that can be used for simple values, we often want to represent structured values. For example, we might want to represent a date in history, a point in two-dimensional space, and so on. In Java, a variable that is of a reference type is used to refer to a structured value.
For example, in order to represent a point in two-dimensional space, the package java.awt provides a ‘class declaration’ called Point. Such a class declaration automatically provides a reference type called Point, and we can declare a variable called myPoint to be of this reference type by the declaration:
0109: java.awt.Point myPoint;To avoid having to repeat the package name every time we want to use Point, we can use an import declaration at the start of the file containing the Java source code:
0110: import java.awt.Point;Having done this, we can declare the variable myPoint by:
0111: Point myPoint;
Such a declaration only introduces a
reference variable,
a variable that can refer to an object
that contains the details about the point.
In some ways, a reference variable is like a
pointer variable in Pascal, C or C++.
Having declared the reference variable, we ought to get it to refer to a Point object. This is done by using an assignment statement where the RHS contains a class instance creation expression:
0112: myPoint = new Point(100,200);The creation expression new Point(100,200) uses a ‘constructor’ for the class Point to create an object of that class with x and y fields of 100 and 200. We will see later that we can do this because this kind of constructor has been provided by the designers of the java.awt package. Often a class provides several different constructors, e.g., as well as a constructor that has two parameters which are the x and y coordinates, the designers of the class Point could also have provided a constructor to construct a Point from a String:
0113: myPoint = new Point("100:200");
but they chose not to do this.
So we now have a variable called
myPoint
that refers to a point that has the x and y coordinates 100 and 200.
The above declaration of myPoint together with the above assignment statement can be shortened to a declaration that has an initializer:
0114: Point myPoint = new Point(100,200);
We can use the dot notation to refer to the fields of an object, e.g., we can use myPoint.x and myPoint.y. For example, we could change the point being represented by 10 units in the x direction and 20 units in the y direction by the assignment statements:
0115: myPoint.x += 10; 0116: myPoint.y += 20;
The designers of the java.awt package have thought that we may want to move an existing point to a new point in space, and so they have provided a method to do this. A method is what would be called a function or procedure in other programming languages. The method that they have provided is called translate. So, instead of the above two assignment statements, we could write:
0117: myPoint.translate(10,20);Note that the dot notation that we used above to refer to the two fields of a Point object is also used in the call of a method. You should look at this call in the following way: ‘apply the translate method with arguments 10 and 20 to the myPoint object’. Note: you would have written something like: translate(myPoint,10,20) in languages like Pascal and C.
0118: Point otherPoint; 0119: otherPoint = myPoint;The assignment statement causes otherPoint to refer to the same object that myPoint refers to.
So, the above assignment statement does not produce a clone. The classes of the Core APIs use two different ways of enabling you to produce a clone of an object:
0120: Point clonePoint; 0121: clonePoint = new Point(myPoint);
The == operator in the following condition is asking whether the two reference variables refer to the same object:
0122: if ( myPoint == otherPoint ) { ... } else { ... }
0123: if ( myPoint.equals(clonePoint) ) { ... } else { ... }
If a reference variable has the value null, then this means that the variable does not currently refer to any object. An assignment statement can be used to indicate this:
0124: myPoint = null;
0125: if ( myPoint == null ) { ... } else { ... }
Note: whilst null appears to be a keyword of the language,
it is technically the
null literal.
Pascal/C/C++ programs inadvertently dispose/free/delete objects which are still in use:
0126: var p, q:^integer; int *p, *q; int *p, *q;
0127: new(p); p = malloc(sizeof(int)); p = new int;
0128: p^ := 27; *p = 27; *p = 27;
0129: q := p; q = p; q = p;
0130: dispose(p); free(p); delete p;
0131: writeln(q^); printf("%d\n", *q); cout << *q << endl;
And programs often cause memory leaks by
not
using
dispose/free/delete
on unwanted objects.
In Java, you do not delete objects: instead, Java has garbage collection. The garbage collector detects objects no longer in use, and reuses their space. Also, unlike C++, you do not have to provide destructors for classes.