Anonymous Classes – Nested Type Declarations

9.6 Anonymous Classes

Declaring Anonymous Classes

Classes are usually first defined and then instantiated using the new operator. Anonymous classes combine the process of definition and instantiation into a single step. Anonymous classes are defined at the location they are instantiated, using additional syntax with the new operator. As these classes do not have a name, an instance of the class can only be created together with the definition. Like local classes, anonymous classes are inner classes that can be defined in static and non-static context.

An anonymous class can be defined and instantiated in contexts where a reference value can be used—that is, as expressions that evaluate to a reference value denoting an object of the anonymous class. Anonymous classes are typically used for creating objects on the fly in contexts such as the value in a return statement, an argument in a method call, or in initialization of variables. The reference value of an anonymous class object can be assigned to any kind of variable (fields and local variables) whose type is a supertype of the anonymous class.

An anonymous class cannot be declared with an access modifier, nor can it be declared static, final, or abstract.

Typical uses of anonymous classes are to implement event listeners in GUI-based applications, threads for simple tasks (see examples in Chapter 22, p. 1365), and comparators for providing a total ordering for objects (see Example 14.11, p. 772).

Extending an Existing Class

The following syntax can be used for defining and instantiating an anonymous class that extends an existing class specified by superclass name:

Click here to view code image

new
superclass_name
<
optional_type_arguments
> (
optional_constructor_arguments
)
{
member_declarations
}

Optional type arguments and constructor arguments can be specified, which are passed to the superclass constructor. Thus the superclass must provide a constructor corresponding to the arguments passed. No extends clause is used in the construct. Since an anonymous class cannot define constructors (as it does not have a name), an instance initializer can be used to achieve the same effect as a no-arg constructor.

Both static and non-static members can be declared in the class body. An anonymous class can override any instance methods accessible by their simple name from the superclass, but if it extends an abstract class, then it must provide implementation for all abstract methods from the superclass. The declaration is terminated by a semicolon (;), unless the reference value of the resulting object is immediately used to access a member of this object.

Example 9.14 Defining Anonymous Classes

Click here to view code image

// File: AnonClassClient.java
interface IDrawable {                           // (1)
  void draw();
}
//_____________________________________________________________________________
class Shape implements IDrawable {              // (2)
  @Override
  public void draw() { System.out.println(“Drawing a Shape.”); }
}
//_____________________________________________________________________________
class Painter {                                 // (3) Top-level Class
  public Shape createShape() {                  // (4) Non-static Method
    return new Shape() {                        // (5) Extends superclass at (2)
      @Override
      public void draw() { System.out.println(“Drawing a new Shape.”); }
    };
  }
  public static IDrawable createIDrawable() {   // (7) Static Method
    return new IDrawable() {                    // (8) Implements interface at (1)
      @Override
      public void draw() {
        System.out.println(“Drawing a new IDrawable.”);
      }
    };
  }
}
//_____________________________________________________________________________
public class AnonClassClient {
  public static void main(String[] args) {      // (9)
    IDrawable[] drawables = {                   // (10)
        new Painter().createShape(),            // (11) Non-static anonymous class
        Painter.createIDrawable(),              // (12) Static anonymous class
        new Painter().createIDrawable()         // (13) Static anonymous class
    };
    for (IDrawable aDrawable : drawables)       // (14)
      aDrawable.draw();
    System.out.println(“Anonymous Class Names:”);
    System.out.println(drawables[0].getClass().getName());// (15)
    System.out.println(drawables[1].getClass().getName());// (16)
  }
}

Output from the program:

Drawing a new Shape.
Drawing a new IDrawable.
Drawing a new IDrawable.
Anonymous Class Names:
Painter$1
Painter$2

Class declarations from Example 9.12 are adapted to use anonymous classes in Example 9.14. The non-static method createShape() at (4) defines a non-static anonymous class at (5), which extends the superclass Shape. The anonymous class at (5) overrides the inherited method draw() from the superclass Shape at (2).

Click here to view code image

// …
class Shape implements IDrawable {          // (2)
  @Override public void draw() { System.out.println(“Drawing a Shape.”); }
}
class Painter {                             // (3) Top-level Class
  public Shape createShape() {              // (4) Non-static Method
    return new Shape() {                    // (5) Extends superclass at (2)
      @Override public void draw() { System.out.println(“Drawing a new Shape.”); }
    };
  }
  // …
}
// …

Leave a Reply

Your email address will not be published. Required fields are marked *