Expressions and Run-time Checks

15.5 Expressions and Run-time Checks

If the type of an expression is a primitive type, then the value of the expression is of that same primitive type.

15.5 Expressions and Run-time Checks EXPRESSIONS

If the type of an expression is a reference type, then the class of the referenced object, or even whether the value is a reference to an object rather than null , is not necessarily known at compile time. There are a few places in the Java programming language where the actual class of a referenced object affects program execution in a manner that cannot be deduced from the type of the expression. They are as follows:

• Method invocation (§15.12). The particular method used for an invocation o.m(...) is chosen based on the methods that are part of the class or interface that is the type of o . For instance methods, the class of the object referenced by the run-time value of o participates because a subclass may override a specific method already declared in a parent class so that this overriding method is invoked. (The overriding method may or may not choose to further invoke the original overridden m method.)

• The instanceof operator (§15.20.2). An expression whose type is a reference type may be tested using instanceof to find out whether the class of the object referenced by the run-time value of the expression is assignment compatible (§5.2) with some other reference type.

• Casting (§5.5, §15.16). The class of the object referenced by the run-time value of the operand expression might not be compatible with the type specified by the cast. For reference types, this may require a run-time check that throws an exception if the class of the referenced object, as determined at run-time, is not assignment compatible (§5.2) with the target type.

• Assignment to an array component of reference type (§10.5, §15.13, §15.26.1). The type-checking rules allow the array type S [] to be treated as a subtype of T [] if S is a subtype of T , but this requires a run-time check for assignment to an array component, similar to the check performed for a cast.

• Exception handling (§14.20). An exception is caught by a catch clause only if the class of the thrown exception object is an instanceof the type of the formal parameter of the catch clause.

Situations where the class of an object is not statically known may lead to run-time type errors.

In addition, there are situations where the statically known type may not be accurate at run-time. Such situations can arise in a program that gives rise to compile-time unchecked warnings. Such warnings are given in response to operations that cannot

be statically guaranteed to be safe, and cannot immediately be subjected to dynamic checking because they involve non-reifiable (§4.7) types. As a result, dynamic

EXPRESSIONS Normal and Abrupt Completion of Evaluation 15.6

checks later in the course of program execution may detect inconsistencies and result in run-time type errors.

A run-time type error can occur only in these situations: • In a cast, when the actual class of the object referenced by the value of the

operand expression is not compatible with the target type specified by the cast operator (§5.5, §15.16); in this case a ClassCastException is thrown.

• In an automatically generated cast introduced to ensure the validity of an operation on a non-reifiable type (§4.7).

• In an assignment to an array component of reference type, when the actual class of the object referenced by the value to be assigned is not compatible with the actual run-time component type of the array (§10.5, §15.13, §15.26.1); in this case an ArrayStoreException is thrown.

• When an exception is not caught by any catch clause of a try statement (§14.20); in this case the thread of control that encountered the exception first attempts to invoke an uncaught exception handler (§11.3) and then terminates.