The cast operator is used for type casting, assigning a value of one type to a variable of another type. Usually, it is used to enable conversions that would otherwise not be allowed by the compiler. We used type casting, for example, when we discussed integer division, the char type as a numeric type, and assigning a class reference to a variable that has a type of one of the implemented interfaces:
int i1 = 11;
int i2 = 3;
System.out.println((float)i1 / i2); //prints: 3.6666667
System.out.println((int)a); //prints: 97
IntrfA intA = (IntrfA)classA;
There are two potential issues to watch while casting:
- In the case of primitive types, the value should be smaller than the maximum value the target type can hold (we will talk about this in detail in the Widening and narrowing conversion of primitive types section later)
- In the case of reference types, the left-hand operand should be a parent (even if indirect) of the right-hand operand, or the left-hand operand should be an interface implemented (even if indirectly) by the class represented by the right-hand operand:
interface I1{}
interface I2{}
interface I3{}
class A implements I1, I2 {}
class B extends A implements I3{}
class C extends B {}
class D {}
public static void main(String[] args) {
C c = new C(); //1
A a = (A)c; //2
I1 i1 = (I1)c; //3
I2 i2 = (I2)c; //4
I3 i3 = (I3)c; //5
c = (C)a; //6
D d = new D(); //7
//a = (A)d; //8 compilation error
i1 = (I1)d; //9 run-time error
}
In this code, case 6 is possible because we know that object a was originally cast based on object c, so we can cast it back to type C and expect it to be fully functional as an object of class C.
Case 8 does not compile because its parent-child relations can be verified by the compiler.
Case 9 is not so easy for the compiler for reasons that are outside the scope of this book. So, while writing code, the IDE will not give you a hint and you may think everything will work as you expect. But then at run-time, you can get ClassCastException:
![](assets/c7514f1c-0e5b-4e2e-8520-35b894fdcf81.png)
Programmers are as happy to see it as much as they like to see the NullPointerException or ArrayOutOfBoundException we demonstrated before. That's why casting to an interface has to be done with more care than to a class.
It is also possible to cast a primitive type to a matching reference type:
Integer integer1 = 3; //line 1
System.out.println(integer1); //prints: 3
Integer integer2 = Integer.valueOf(4);
int i = integer2; //line 4
System.out.println(i); //prints: 4
In line 1 and line 4, casting is done implicitly. We will discuss such a casting (also called conversion, or boxing and unboxing) in more detail in the Boxing and unboxing between a primitive and reference types section later.