Typecasting is one of the most important concepts which basically deals with the conversion of one data type to another datatype implicitly or explicitly. In this article, the concept of downcasting for objects is discussed. It’s putting the parent’s reference variable holding the child’s object to the child’s reference variable. Downcasting cannot be implicit. The syntax of downcasting is:
Type_A ref1 = new Type_B(); Type_C ref2 = (Type_D) ref1;
In this statement, two operations are performed:
- converting an object referred by ref1 to type D
- assigning this converted object of type D to a reference variable of type C
There are 3 rules which are checked if the downcasting will be successful or not. The rules are as discussed below:
1. Check for valid conversion
For the conversion to be valid, Type A and Type D must have a relation between them. This relation can be either type A is the parent of type D, or type D is the parent of type A or type A = type D. If there is no such relation, then there will be a compile-time error. This rule is checked by the compiler and hence it doesn’t consider the type of object created in ref1 i.e it only considers type A and type D, not type B (which is the actual type of runtime object created). Considering this rule, let’s see some statements which satisfy the criteria.
Object ref1 = new String(); String ref2 = (String) ref1; // satisfy rule 1 ref1 is of Object type which is parent of String Object ref1 = new String(); Integer ref2 = (Integer) ref1 ; // satisfy rule 1 ref1 is of Object type which is parent of Integer String ref1 = new String(); String ref2 = (String) ref1 ; // satisfy rule 1 ref1 is of String type which is same String ref1 = new String(); String ref2 = (Object) ref1 ; // satisfy rule 1 ref1 is of String type which is child of Object String ref1 = new String(); String ref2 = (Integer) ref1; // doesn't satisfy rule 1 ref1 is of String type which is not related to Integer Error: incompatible types: String cannot be converted to Integer
2. Check for a valid assignment
After downcasting, the type of the object will be typed D. We know that an object can be referred to by either the same type or its parent. This leads to the second rule that the type of ref2, type C must be a parent or the same as type D. If this rule is not satisfied then the compiler will throw an error. Considering this rule, let’s see some statements which satisfy the criteria.
Object ref1 = new String(); Object ref2 = (String) ref1 ; // satisfy rule 1 & rule 2 downcasted object of String type is referred by parent type Object Object ref1 = new String(); Integer ref2 = (Integer) ref1; // satisfy rule 1 & rule 2 downcasted object of Integer type is referred by same type Object ref1 = new String(); String ref2 = (Object) ref1; // satisfy rule 1 but not rule 2 downcasted object of Object type is referred by child class type String Error: incompatible types: Object cannot be converted to String String ref1 = new String(); Integer ref2 = (Integer) ref1; // doesn't satisfy rule 1 & rule 2 downcasted object of Integer type is referred by unrelated class type String Error: incompatible types: String cannot be converted to Integer
3. Check the Compatibility of the runtime type of object
If we notice the above two points, they cover only the reference types and the converted type. The actual runtime type of the object we are trying to downcast is not yet taken into consideration. This runtime type will now be considered by JVM to check for validity. The child class object can be cast to the same class or parent class. This leads to the third runtime rule which is that type D must be a parent or same as of runtime type of ref1 i.e type B. If this condition fails, the JVM will throw ClassCastException at runtime. Considering this rule, let’s see some statements which satisfy the criteria.
Object ref1 = new String(); Object ref2 = (String) ref1 ; // satisfy rule 1, rul2 & rule 3 downcasted object of String type is same as runtime type String Object ref1 = new Integer(); Object ref2 = (Number) ref1 ; // satisfy rule 1, rul2 & rule 3 downcasted object of Number type is same parent of runtime type Integer Object ref1 = new String(); Integer ref2 = (Integer) ref1; // satisfy rule 1, rule 2 but not rule 3 downcasted object of Integer type is not same or parent of runtime type String Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer