Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Study guide: Object-oriented language basics, Part 5

Brush up on Java terms, learn tips and cautions, and review homework assignments

  • Print
  • Feedback

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:
  1. Every class that implicitly or explicitly extends Object inherits a protected clone() method
  2. Only code within a class can call its inherited protected clone() method
Jeff

Homework

This month's homework centers on three questions:
  1. Why is it not a good idea to add extends Object to a class declaration?
  2. How would you deeply clone an array of String objects?
  3. 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 ());
   }
}


  • Print
  • Feedback

Resources