Contents | Prev | Next Inner Classes Specification

Other changes in the Java 1.1 language

The Java 1.1 language includes four additional extensions which fill small holes in the language, and make certain kinds of APIs easier to use.

Instance initializers

The static initializer syntax is extended to support instance initialization also:


Initialization code introduced without the static keyword is executed by every constructor, just after the superclass constructor is called, in textual order along with any instance variable initializations.

An instance initializer may not return, nor throw a checked exception, unless that exception is explicitly declared in the throws clause of each constructor. An instance initializer in an anonymous class can throw any exceptions.

Instance initializers are useful when instance variables (including blank finals) must be initialized by code which must catch exceptions, or perform other kinds of control flow which cannot be expressed in a single initializer expression. Instance initializers are required if an anonymous class is to initialize itself, since an anonymous class cannot declare any constructors.

Anonymous array expressions

The array allocation syntax is extended to support initialization of the elements of anonymous arrays. Just as a named array can be initialized by a brace- enclosed list of element expressions, an array creation expression can now be followed by such a brace-enclosed list. In both cases, the array type is not allowed to include any dimension expressions; the dimension is computed by counting the number of element expressions. Here is the new syntax:

        new Type Dims ArrayInitializer

The equivalence of the following two statements illustrates the new syntax:

            T v[] = {a};
            T v[] = new T[] {a}; 

Class literals

. class
        void . class

A class literal is an expression consisting of the name of a class, interface, array, or primitive type followed by a `.' and the token class. It evaluates to an object of type Class, the class object for the named type (or for void).

For reference types, a class literal is equivalent to a call to Class.forName with the appropriate string, except that it does not raise any checked exceptions. (Its efficiency is likely to be comparable to that of a field access, rather than a method call.) The class literal of a reference type can raise NoClassDefFoundError, in much the same way that a class variable reference can raise that error if the variable's class is not available.

The class literal of a primitive type or void is equivalent to a static variable reference to a pre-installed primitive type descriptor, according to this table:

        boolean.class   ==   Boolean.TYPE
        char.class      ==   Character.TYPE
        byte.class      ==   Byte.TYPE
        short.class     ==   Short.TYPE
        int.class       ==   Integer.TYPE
        long.class      ==   Long.TYPE
        float.class     ==   Float.TYPE
        double.class    ==   Double.TYPE
        void.class      ==   Void.TYPE

Java APIs which require class objects as method arguments are much easier to use when the class literal syntax is available. Note that the compiler is responsible for taking into account the ambient package and import statements when processing the TypeName of a class literal.

The older usage of Class.forName requires the programmer to figure out the desired package prefix and write it in a class name string. The difficulty of getting the string spelled right becomes greater in the presence of inner classes, since their names (as processed by Class.forName) are encoded with `$' characters instead of dots.

Note that a class literal never contains an expression, only a type name.

Blank finals and final local variables

A blank final is final variable declaration (of any kind) which lacks an initializer. A blank final must be assigned an initial value, at most once.

The definite assignment rules are extended to record variables which are "definitely unassigned," and an assignment to a blank final is prohibited unless the final is definitely unassigned before the assignment statement. Subsequently, it is definitely assigned, and, being a final, it cannot be re- assigned along the same execution path.

The definite unassignment rules take into account back-branches of loops, so that a variable occurrence in a loop body may not be definitely unassigned if the loop makes an assignment which can reach the occurrence via a back- branch. The definite assignment checks work as if the first iteration of the loop had been unrolled into an if statement.

A blank final class variable must be definitely assigned by a static initializer (in the same class). This is the only context where class variables are checked for definite assignment.

A blank final instance variable must be definitely assigned by a non-static initializer, or else by every constructor. These are the only contexts in which definite assignment checking is done on instance variables. Within these contexts, an assignment to this.V is recognized as performing an assignment to the name V for purposes of definite assignment checking.

Local variables and parameters of all sorts can now be declared final:

Opt Type VariableDeclarators

Opt Type VariableDeclaratorId

Such a variable is subject to the usual definite assignment rules governing local variables. In addition, it cannot be assigned to, except for initialization.

A method parameter or catch formal parameter may be declared final. This has no effect on the method signature or the caught exception type. Within the body of the method or catch, the parameter may not be assigned to.

The final declaration modifier may be used to make local variables and parameters available to inner classes.

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