Keywords: current

Next: 1.5.3.2 Avoiding the Use Up: 1.5.3 Singleton Pattern Previous: 1.5.3 Singleton Pattern

### 1.5.3.1 Type Predicates and Type Casts in Java

In Java, all reference (object) types are subtypes of the universal type `Object`. If we ignore the eight primitive types (which all have corresponding wrapper types in the `Object` type hierarchy), then `Object` is the universal type to which all program values belong.

To test membership in particular object types, Java provides a collection of postfix operators of the form

> `instanceof T`

where `T` is any defined object type. Hence, given the preceding program defining type `IntList`, Java interprets the program expressions below as follows:

> `new Empty() instanceof Empty` `true`
> `new Cons(0, new Empty()) instanceof Empty` `false`
> `"A" instanceof Empty` `false`

The `instanceof` operator has the same precedence as the relational operators. (Although the second ``argument'' to `instanceof` must be a type name, the Java parser initially recognizes this argument as an expression.)

Finger exercise: Load the sample program `IntList.java` into the DrJava Definitions pane. Add definitions for `isEmpty` and `isCons`. In the Interactions pane try evaluating the following sequence of interactive computations:

    IntList empty = new Empty();
    empty
    IntList oneElt = new Cons(1, empty);
    oneElt
    empty.isEmpty()
    empty.isCons()
    oneElt.getFirst()
    oneElt.isEmpty()
    oneElt.isCons()
    IntList twoElts = new Cons(0, oneElt);
    twoElts.getFirst()
    twoElts.getRest()
    twoElt.getRest().isCons()
    empty.getFirst()
    empty.getRest()
    "A".isEmpty()
    "A".isCons()

Perform the equivalent sequence of membership tests as in the previous exercise using `instanceof` operators instead of the operations `isEmpty` and `isCons`.

To accomodate static type checking, Java includes type coercion functions called casts. You may have noticed that Java includes operations for casting one primitive type to another. These primitive type casts convert values of one type to ``corresponding'' values of another type. The casting operations for object types have a completely different meaning; casting a value v to an object type T peforms an `instanceof` check on v provided v is not `null`. If the check returns `false`, then Java throws a `ClassCastException` indicating that the cast failed. If this exception is not caught (see Section 1.11.3), Java aborts execution and prints an error message indicating which cast failed. In contrast, primitive type casts never fail!

Casting the `null` value to an object type always succeeds, so a value that has been cast to a particular type T can still generate a `NullPointerException` if it is subsequently used as the receiver in a method call.

If object type casts can only cause a program to abort execution, what good are they? Since the cast prevents execution from continuing if the `instanceof` test fails, the compiler knows that the result of object casting expression

> `(` T`)` e

has type T. Consequently, the static type checker in the compiler assigns the static type T to this casting expression. By inserting object casting operations in a program, you can tell the static type checker that a particular expression has a narrower (more precise) type that the type that would otherwise be assigned by the static type checking rules.

Finger exercise: Load the preceding definition of the IntList class and subclasses the DrJava Definitions pane. Save your code in the file `IntList.java`. In the Interactions pane try evaluating the following sequence of interactive computations:

    IntList empty = new Empty();
    IntList oneElt = new Cons("B", empty);
    oneElt
    oneElt.first
    ((Cons) oneElt).first
    oneElt.rest
    ((Cons) oneElt).rest

Perform the equivalent sequence of membership tests as in the previous exercise using `instanceof` operators instead of the operations `isEmpty` and `isCons`.

Next: 1.5.3.2 Avoiding the Use Up: 1.5.3 Singleton Pattern Previous: 1.5.3 Singleton Pattern