Previous Table of Contents Next


14.3.6.7. Finalizer Chaining?

You might assume that since Java chains constructor methods that it also automatically chains the finalizer methods for an object. In other words, you may think that the finalizer method of a class automatically invokes the finalizer of its superclass. In fact, Java does not do this. In practice, finalizer methods are relatively rare, and the need for finalizer chaining rarely arises. If a class B with a finalizer method is a subclass of a class A with its own finalizer method, then B’s finalizer should be sure to invoke A’s finalizer, explicitly creating a chain of finalizers. This is a little tricky, since finalizers always have the same name (finalize()), and we haven’t yet learned how to invoke a method in the superclass when that method is also defined in the subclass. We’ll return to the issue of finalizer chaining when we learn how.

14.3.6.8. Shadowed Variables

Suppose that our GraphicCircle class has a new variable that specifies the resolution, in dots per inch, of the DrawWindow object in which it is going to be drawn. And further, suppose that it names that new variable r:

   public class GraphicCircle extends Circle {
       Color outline, fill;
       float r;  // New variable. Resolution in dots-per-inch.
       public GraphicCircle(double x, double y,
           double rad, Color o, Color f) {
           super(x, y, rad); outline = o; fill = f;
       }
       public void setResolution(float resolution) { r = resolution; }
       public void draw(DrawWindow dw)
           { dw.drawCircle(x, y, r, outline, fill); }
   }

Now, with this resolution variable declared, when we use the variable r in the GraphicCircle class, we are no longer referring to the radius of the circle. The resolution variable r in GraphicCircle shadows the radius variable r in Circle.20


20This is a contrived example, of course—we could simply rename the variable and avoid the issue. Typically, we would rename the variable: Variable shadowing is a necessary part of Java syntax, but is not a useful programming technique. Your code will be easier to understand if you avoid shadowed variables.

So, how can we refer to the radius variable defined in the Circle class when we need it? Recall that using a variable, such as r, in the class in which it is defined is shorthand for:

   this.r  // Refers to the GraphicCircle resolution variable.

As you might guess, you can refer to a variable r defined in the superclass like this:

   super.r  // Refers to the Circle radius variable.

Another way you can do this is to cast this to the appropriate class and then access the variable:

   ((Circle) this).r

This cast is exactly what the super keyword does when used like this. You can use this casting technique when you need to refer to a shadowed variable defined in a class that is not the immediate superclass. For example, if C is a subclass of B, which is a subclass of A, and class C shadows a variable x that is also defined in classes A and B, then you can refer to these different variables from class C as follows:

   x                // Variable x in class C
   this.x           // Variable x in class C
   super.x          // Variable x in class B
   ((B)this).x      // Variable x in class B
   ((A)this).x      // Variable x in class A
   super.super.x    // Illegal; does not refer to x in class A.

Note that you cannot refer to a shadowed variable x in the superclass of a superclass with super.super.x. Java does not recognize this syntax.

14.3.6.9. Shadowed Methods?

Just as a variable defined in one class can shadow a variable with the same name in a superclass, you might expect that a method in one class could shadow a method with the same name (and same arguments) in a superclass. In a sense, they do: “Shadowed” methods are called overridden methods. But method overriding is significantly different than variable shadowing; it is discussed in the sections that follow.

14.3.7. Overriding Methods

When a class defines a method using the same name, return type, and arguments as a method in its superclass, the method in the class overrides the method in the superclass. When the method is invoked for an object of the class, it is the new definition of the method that is called, not the superclass’s old definition.

Method overriding is an important and useful technique in object-oriented programming. Suppose we define a subclass Ellipse of our Circle class.21 Then it would be important for Ellipse to override the area() and circumference() methods of Circle. Ellipse would have to implement new versions of these functions because the formulas that apply to circles don’t work for ellipses.


21This is admittedly a strange thing to do, since, mathematically, a circle is a kind of ellipse, and it is customary to derive a more specific class from a more general one. Nevertheless, it is a useful example here.

Before we go any further with the discussion of method overriding, be sure that you understand the difference between method overriding and method overloading, which we discussed earlier. As you probably recall, method overloading refers to the practice of defining multiple methods (in the same class) with the same name but with differing argument lists. This is very different from method overriding, and it is important not to get them confused!


Previous Table of Contents Next