1. Introduction
ClassCastException is one of the most common exceptions you will probably encounter in your journey as a Java developer. In this quick tutorial, you will learn how to reproduce the exception and also how to fix it.
2. What Java Says about ClassCastException
According to the Javadoc, a ClassCastException is thrown to indicate an attempt to cast an object to a subclass of which it is not an instance.
3. How to Reproduce
3.1. Incorrect Use of Generics
It’s always malpractice to use raw types in collections as it may lead to unexpected situations.
In the following code, we are creating a raw List
in which we are putting both strings and integers.
List rawList = new ArrayList();
rawList.add("hello");
rawList.add(1);
String value = (String) rawList.get(1);//ClassCastException
System.out.println(value);
Running the code will produce the following output:
Exception in thread "main" java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader 'bootstrap')
at Scratch.main(scratch_2.java:25)
As you can see the exception is due to the fact we stored an Integer
value (1) and attempted to cast it to a String
. Since we are using a raw collection, this error cannot be prevented at compile time.
One way of fixing this is to use the correct type when casting:
List rawList = new ArrayList();
rawList.add("hello");
rawList.add(1);
Integer value = (Integer) rawList.get(1);
System.out.println(value);
Output
1
However, a better way of dealing with this error is to avoid raw types in collections.
List<String> list = new ArrayList();
list.add("hello");
list.add("1");//Compilation error if you put list.add(1)
String value = list.get(1);
System.out.println(value);
The takeaway here is to avoid using raw types in collections
3.2. Incorrect DownCasting
Downcasting is the process of casting an object of class type A to an object of class type B, where B is a subclass of A. Incorrect downcasting is a common source of ClassCastException.
Let’s assume that we have the following classes:
class Animal {
void cry(){
System.out.println("I don't know");
}
}
class Dog extends Animal {
void cry(){
System.out.println("Bark...");
}
}
class Cat extends Animal {
void cry(){
System.out.println("Meow...");
}
}
The following code is an example of incorrect downcasting:
public static void main(String[] args) throws Exception {
Animal animal = new Animal();
Dog dog = (Dog) animal;//ClassCastException
dog.cry();
}
Running the code above with produce the following output:
Exception in thread "main" java.lang.ClassCastException: class Animal cannot be cast to class Dog (Animal and Dog are in unnamed module of loader 'app')
at Scratch.main(scratch_2.java:23)
As you can see, a ClassCastException is thrown because the object “animal” is not of type “Dog”.
How To Fix
You should ensure to create an actual “Dog” object in this way:
Animal animal = new Dog();//Create a Dog object, not an Animal object.
Dog dog = (Dog) animal;
dog.cry();
Output:
Bark...
3.3. Casting between sibling types
Another common situation in which this exception occurs is when attempting to cast two “sibling” classes.
Assuming that Dog
and Cat
both extends Animal
, the following code will throw a ClassCastException
.
Animal animal = new Dog();
Cat cat = (Cat) animal;//ClassCastException
cat.cry();
Output:
Exception in thread "main" java.lang.ClassCastException: class Dog cannot be cast to class Cat (Dog and Cat are in unnamed module of loader 'app')
at Scratch.main(scratch_2.java:23)
Technically, this is a forbidden operation because you cannot cast objects of two classes that only share a superclass.
4. Conclusion
In this brief tutorial, you learned about the ClassCastException and how to fix it.
You can find the complete code of this article here in GitHub