Study guide: Object-oriented language basics, Part 5
Brush up on Java terms, learn tips and cautions, and review homework assignments
By Jeff Friesen, JavaWorld.com, 08/03/01
Glossary of terms
- deep cloning
- A process where the
clone() method duplicates a composite object's contained objects.
- finalization
- The act of the garbage collector calling an object's
finalize() method to perform cleanup tasks prior to the object's garbage collection.
- garbage collector
- JVM code dedicated to reclaiming the memory occupied by objects no longer in use.
- notification method
- A method that wakes up one or more of several waiting threads.
- shallow cloning
- A process where the
clone() method duplicates the contents of instance fields, but does not duplicate the objects referenced by those fields.
- waiting method
- A method that causes a thread to wait either indefinitely until notified by another thread or for a specific time period if
not notified before the time expires.
Tips and cautions
These tips and cautions will help you write better programs and save you from agonizing over why the compiler produces error
messages.
Tips
- You can obtain a
Class object for any type by appending .class to the type name.
- When you need to compare a class's objects, override that class's
equals() method. Do not rely on the default equals() implementation because that implementation uses == to compare object references—not object contents.
- Consider overriding a class's
toString() method to return a String object that contains the current values of the class's fields. Those values are useful for debugging purposes.
Cautions
- It is illegal to call
Object's getClass() method on a primitive type.
- When assigning a
clone() method call's returned reference to a reference variable, you must explicitly cast the reference to the reference variable's
type. Otherwise, the compiler reports an error.
- Because you can't clone
String objects, attempts to call String's inherited clone() method result in compiler errors.
- Do not use
== to compare two objects' contents. The == operator only compares two object references—not the objects' contents.
Reader questions
Find out what questions your fellow readers are asking and my answers to those questions.
Jeff,
I have difficulty understanding the effect or implications of overriding the clone method inside the AnotherClass in Listing 6, CloneDemo2.java. Unfortunately, you didn't explain the reason as to why overriding the clone method produces the result it does. Could you
clarify this please?
Heejoon Park
Heejoon, Listing 6's
CloneDemo2.java is a continuation of Listing 5's
CloneDemo1.java example. For reference, here is the
CloneDemo1.java source code:
// CloneDemo1.java
class CloneDemo1 implements Cloneable
{
int instanceField = 3;
public static void main (String [] args) throws
CloneNotSupportedException
{
CloneDemo1 cd1 = new CloneDemo1 ();
CloneDemo1 x = (CloneDemo1) cd1.clone ();
System.out.println (x.instanceField);
AnotherClass ac = new AnotherClass ();
// AnotherClass y = (AnotherClass) ac.clone ();
}
}
class AnotherClass
{
int anotherInstanceField = 2;
}
A close look at
CloneDemo1.java reveals the following comment:
// AnotherClass y = (AnotherClass) ac.clone (); I included that comment so that
CloneDemo1.java would compile. If I uncomment that code, the compiler reports the following error:
CloneDemo1.java:17: clone() has protected access in java.lang.Object
AnotherClass y = (AnotherClass) ac.clone ();
Class
Object, located in package
java.lang, declares a protected
clone() method. A
protected method can be called by code from any class in the same package as the class that contains the protected method, or by code
from any subclass regardless of package. (I briefly talk about this protected concept in "
Object-Oriented Language Basics, Part 2"). Both
CloneDemo1 and
AnotherClass implicitly extend
Object. That means each class inherits its own protected
clone() method. Due to the above protected method rule,
CloneDemo1 can't call
AnotherClass's inherited protected
clone() method, and
AnotherClass can't call
CloneDemo1's inherited protected
clone() method. Want proof? Try compiling the following variant of the
CloneDemo1.java source code:
// CloneDemo1.java
class CloneDemo1 implements Cloneable
{
int instanceField = 3;
public static void main (String [] args) throws
CloneNotSupportedException
{
CloneDemo1 cd1 = new CloneDemo1 ();
CloneDemo1 x = (CloneDemo1) cd1.clone ();
System.out.println (x.instanceField);
AnotherClass ac = new AnotherClass ();
// AnotherClass y = (AnotherClass) ac.clone ();
}
}
class AnotherClass
{
int anotherInstanceField = 2;
void foo ()
{
CloneDemo1 cd1 = new CloneDemo1 ();
CloneDemo1 cd2 = (CloneDemo1) cd1.clone ();
}
}
When the compiler tries to compile
foo()'s
CloneDemo1 cd2 = (CloneDemo1) cd1.clone (); statement, the compiler reports the same protected access error. For
CloneDemo1's
main() method to successfully execute
AnotherClass y = (AnotherClass) ac.clone ();, we must override the inherited protected
clone() method with our own
clone() method and call the superclass (that is,
Object)
clone() method from the overridden method. The following code fragment (from
CloneDemo2.java) illustrates:
AnotherClass implements Cloneable
{
int anotherInstanceField = 2;
protected Object clone () throws CloneNotSupportedException
{
return super.clone ();
}
}
You can declare the overridden
clone() method protected because that method's class --
AnotherClass -- and
CloneDemo1 are in the same unnamed package. As a result,
CloneDemo1's
main() method can call
AnotherClass's overridden
clone() method. Keep the following two points in mind, and you should experience no further difficulty with this topic:
- Every class that implicitly or explicitly extends
Object inherits a protected clone() method
- Only code within a class can call its inherited protected
clone() method
Jeff
Homework
This month's homework centers on three questions:
- Why is it not a good idea to add
extends Object to a class declaration?
- How would you deeply clone an array of
String objects?
- Why doesn't the
String class allow you to clone String objects? (Hint: Think of immutability.)
Answers to last month's homework
Last month, I asked you to complete a
Shapes application by introducing a
Rectangle class and using implementation inheritance to derive
Rectangle from
Square. The code below presents the result:
Shapes.java
// Shapes.java
class Point
{
private double x, y;
Point (double x, double y)
{
this.x = x;
this.y = y;
}
double getX ()
{
return x;
}
double getY ()
{
return y;
}
}
class Square
{
private double width;
Square (double width)
{
this.width = width;
}
double getWidth ()
{
return width;
}
}
class Rectangle extends Square
{
private double length;
Rectangle (double width, double length)
{
// Pass the width parameter value to the Square layer, so that
// layer can initalize.
super (width);
this.length = length;
}
double getLength ()
{
return length;
}
}
class Shapes
{
public static void main (String [] args)
{
Square s = new Square (100);
System.out.println ("s.width = " + s.getWidth ());
Rectangle r = new Rectangle (50, 25);
System.out.println ("r.width = " + r.getWidth ());
System.out.println ("r.length = " + r.getLength ());
}
}