In Scheme every primitive operation dynamically checks that its arguments have the appropriate form (type) as it executes. If an operation is applied to data of the wrong form, Scheme aborts execution and prints an error message, much as Java does when an exception is thrown and not caught.
Java also performs some argument checking during program execution (run-time), but most argument checking is done statically by the compiler before a Java program executes. A Java compiler enforces a syntactic discipline on program text called static typing. The compiler uses a collection of type-checking rules to determine whether a program is well-typed or not. Programs that are not well-typed are rejected with an explanation of which rules were broken.
The type-checking rules embody simple ``common sense'' inferences and consistency checks. The rules assign a type to every program expression and subsequently check that these type assignments are consistent. A Java compiler assigns types to program expression as follows:
test ? consequent : alternativehas the more general type of the consequent type and alternative;1.5 and
T eis T.
Given these type assignments, a Java compiler checks their consistency by enforcing the following rules:
Note that Java type checking rules do not capture the logical consequences of instanceof tests. As a result, Java program text often must include apparently redundant casting operations in code following an instanceof test.
This phenomenon is illustrated in the following simple example. Consider the following method which could be added to the IntList class above.
In the method, all occurrences of the parameter l have the same type, namely IntList as declared in the method header. Thestatic Object first(IntList l) { if (l instanceof Cons) return ((Cons) l).first; else throw new ClassCastException("first requires a non-Empty IntList"); }
l instanceof Constest has no effect on type-checking. As a result, the occurrence of l preceding the field extraction operation .first must be explicitly converted to type Cons using the casting operation (Cons) written as a prefix in front of l. Since the field .first is not defined in the abstract class IntList, the definition of the method first does not type check if the casting operation (Cons) is omitted.
Applying a casting operation ( T ) to a Java expression e of some static object type U has consequences for both program execution and compilation. First, it inserts a run-time check to confirm that the value of e belongs to the type T as claimed by the casting operation. Second, it converts the static type of the expression e from U to T.