Previous | Next | Trail Map | To 1.1 -- And Beyond! | Migrating to 1.1

Changes to the Java Language

Inner Classes

Probably the single most significant change to the Java language for JDK 1.1 is the ability to define classes as members of other classes. Such classes are called inner classes and are covered in [PENDING: link to inner classes]

Anonymous Classes

When you are writing simple subclasses or implementations of interfaces, creating a bunch of classes for each trivial class can be awkward. Anonymous classes are a convenient short form of inner classes that have no name, only an implementation that is specified right along with the new.

For a brief discussion of anonymous classes and an example that uses one, refer to [PENDING: link to inner classes].

Instance Initializers

In JDK 1.0.2, the Java language supported static initializers that let you initialize class variables.
class ClassWithStaticInitializer {
    static {
	// ... initialization code ...
    }
}
JDK 1.1 adds a similar syntax for performing instance initialization:
class ClassWithInstanceInitializer {
    {
	// ... initialization code ...
    }
}
Initialization code introduced without the static keyword is executed by every constructor, just after the superclass constructor is called, in the same order that they appear in the source code, 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.

[PENDING: link to new material that talks about this in the book]

Array Initialization

You can initialize the contents of an array when you new it. For example, the following would be a flexible way to create an array of strings:

String[] tutorialTeam = new String[] {
	    "Alison", "Kathy", "Mary"
};
The array allocation syntax is extended to support initialization of the elements of anonymous arrays.

Class literals

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

New Uses for final

Method parameters and local variables can be declared final. If you do not expect to change the value of a parameter or variable inside the method, you can declare it final to let the compiler enforce that. The compiler can also optimize uses of a final parameter or variable since it knows the value will never change.

The final-ness of a parameter is not part of the method signature-it is simply a detail of the implementation. A subclass can override a method and add or drop any final parameter modifiers you wish. You can also add or drop final modifiers in a method's parameters without causing any harm to existing compiled code that uses that method. The final declaration does not show up in the documentation generated from doc comments.

You can defer initialization of a final field or variable, as long as you initialize it before it is used and assign a value to it exactly once. The compiler will check for proper assignment, as will the verifier before code is executed. Deferred initialization can be useful when the proper value can only be calculated by a loop or other code that is hard or impossible to encode in a variable initializer, such as code that throws exceptions that must be caught and handled.

Transient Defined in 1.1

The transient keyword, has defined meaning for 1.1 (whereas it was undefined in 1.0.2. In 1.1, transient is used to mark member variables that should not be saved during object serialization.


Previous | Next | Trail Map | To 1.1 -- And Beyond! | Migrating to 1.1