Witscale Test Center

10.5 Object reference casting > 10.5.1 Compile time rules for reference casting


10.5.1 Compile time rules for reference casting

The compile-time rules are less strict. The following rules illustrate the checks made by Java compiler while casting the references. If your code does not comply with these rules, it will not compile.

 

1.       You can cast one class-type to another class-type if any one of them is a superclass of the other class.

In our example hierarchy, the class Account is a superclass of CheckingAccount. Following code shows a valid cast:

 

CheckingAccount checkingAcc = new CheckingAccount();

Account acc = (Account) checkingAcc;   //Valid casting

 

The above code will compile even without cast due to conversion. Since compile-time checks only require that one of the classes to be the superclass of other, the following cast is also valid.

 

Account acc = new Account();

CheckingAccount checkingAcc = (CheckingAccount) acc; //Valid casting

 

The above code will not compile without the cast operator because it is assigning a wider type to a narrower type. Hence you need to forcefully change the type with casting.

 

2.       You can always cast an interface-type to any non-final class-type.

For instance, the following code cast a Date object to an interface type auditable:

 

Date date = new Date();

Auditable auditable = (Auditable) date;

 

The above code may look weird but it will compile. Even though Date is not implementing the interface Auditable, this kind of cast is valid.

 

The compiler allows a non-final object to be cast to interface in an anticipation that may be some subclass of it would be implementing the interface. In case of final object reference, the compiler definitely knows at compile time that it is not possible for that final object to implement the interface anyway. So it does now allow casting to the final objects that do not implement the interface.

 

3.       You can never cast an array of one primitive type to an array of another primitive type.

For instance, following are all invalid casts and compiler will flag an error:

 

byte[] byteArray = new byte[4];

int[] intArray = (int[]) byteArray;   // Compile time error

 

The above code fails to compile even if the element type int is wider datatype than byte. Compiler throws error because primitive arrays are assignment incompatible with other primitive arrays, you cannot cast or convert them.

 

4.       You can cast an array of references to another array of references, if it is legal to cast their elements.

Since you can cast CheckingAccount to Account, you can also cast CheckingAccount[] to Account[]. The following code compiles without any problem:

 

Account[] accounts = new Account[5];

CheckingAccount[] chkAccounts = (CheckingAccount[]) accounts; //Valid

 

 Note that the cast is required here as we are changing the wider type Account[] to narrower type CheckingAccount[].

The examples we have seen so far compile fine. However, successful compilation does not mean that they will run without any problem. In fact, some of them will definitely fail at runtime because the cast they are performing is not correct. The runtime rules decide which cast is possible to perform at runtime.