Contents | Prev | Next Inner Classes Specification


Why does Java need inner classes?

From the very beginnings of Java, its designers have recognized the need for a construct like a "method pointer," which (in all its various forms) amounts to a handle on an individual block of code which can be used without reference to the object or class containing the code. In languages (like C or Lisp) where functions are free standing, independent of objects, function pointers serve this role. For example, these pointers often serve to connect a "callback" or "event" in one module to a piece of code in another. In a more object oriented style, Smalltalk has "blocks," which are chunks of code that behave like little objects. As with C or Lisp function pointers, Smalltalk blocks can be used to organize complex control flow patterns, such as iteration over collections.

In Java, the same complex control flow patterns, including event management and iteration, are expressed by classes and interfaces. Java uses interfaces with one method where other languages might use separate "function types." The Java programmer creates the equivalent of a callback or a Smalltalk block by wrapping the desired code in an adapter class which implements the required interface. With inner classes, the notation for adapters is about as simple as that of Smalltalk blocks, or of inner functions in other languages. However, since classes are richer than functions (because they have multiple entry points), Java adapter objects are more powerful and more structured than function pointers.

So, whereas C, Lisp, and Smalltalk programmers use variations of "method pointers" to encapsulate chunks of code, Java programmers use objects. Where other languages have specialized function types and notations to encapsulate behavior as functions, Java has only class and interface types. In Java, "the class is the quantum of behavior." One benefit of this approach is simplicity and stability for the Java Virtual Machine, which needs no special support for inner classes or function pointers.

Without inner classes, Java programmers can create callbacks and iterators by means of adapter classes defined at top-level, but the notation is so clumsy as to be impractical. By means of inner classes, Java programmers can write concise adapter classes which are coded precisely where they are needed, and operate directly on the internal variables and methods of a class or a block.

Thus, inner classes make adapter classes practical as a coding style. In the future, inner classes will also be more efficient than equivalent top-level adapter classes, because of increased opportunities for optimization, especially of (externally) inaccessible classes.

Why anonymous classes?

An anonymous class is an abbreviated notation for creating a simple local object "in-line" within any expression, simply by wrapping the desired code in a "new" expression.

As noted previously, not every inner class should be anonymous, but very simple "one-shot" local objects are such a common case that they merit some syntactic sugar.

Anonymous classes are useful for writing small encapsulated "callbacks," such as enumerations, iterators, visitors, etc. They are also helpful for adding behavior to objects which already have names, such as AWT components (to which anonymous event handlers are added), and threads. In both cases, an intervening class name can detract from the clarity of the code.

Several other languages from which Java derives inspiration, such as Smalltalk and Beta, offer similar shorthands for anonyous objects or functions.

What about dynamic typing and computed selectors ("perform")?

In order to support the construction of robust and secure systems, Java is statically typed. In other languages, callbacks sometimes take a form which is untyped, or dynamically typed. C callbacks usually work with an untyped "client data" address, while Smalltalk classes sometimes plug into each other by means of symbolic method references computed at run time, which are passed to an interpretive "perform" method.

The closest equivalent to a C void* pointer in Java is a reference of type Object. As in C, it is possible to program in Java with such "untyped" references. A generic "argument" field in an event descriptor might be an undifferentiated Object, as is the element type of java.util.Vector. Coding with untyped references is sometimes a workable technique, despite the execution costs of dynamic type checking, but the lack of static declarations can make programs hard to understand and maintain.

Also, some applications for "method pointer" constructs, such as application builders or the Java Beans component framework, have needed the ability to invoke a method of a computed name on an arbitrary object. This capability is provided by the Java Core Reflection API, java.lang.reflect, a new Java 1.1 API.


Contents | Prev | Next

Inner Classes Specification (HTML generated by dkramer on March 15, 1997)
Copyright © 1996, 1997 Sun Microsystems, Inc. All rights reserved
Please send any comments or corrections to john.rose@eng.sun.com