In Java, reference casting allows you to change the type of a reference to match the type of the object it refers to. Understanding when and how to use casting is crucial for managing polymorphism and type safety in your code.
When an object is cast to a superclass or interface type, it is called upcasting. Upcasting is always safe and does not require an explicit cast because it involves casting to a more general type.
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
void makeSound() {
System.out.println("Dog barks");
}
void fetch() {
System.out.println("Dog fetches");
}
}
public class TestUpcasting {
public static void main(String[] args) {
Dog dog = new Dog();
Animal animal = dog; // Automatic upcasting
animal.makeSound(); // Outputs "Dog barks" because of polymorphism
}
}
When you cast a reference to a more specific type (subclass), it is called downcasting. Downcasting requires an explicit cast because it involves narrowing the reference to a more specific type. If the actual object is not an instance of the specified subclass, a ClassCastException
will be thrown at runtime.
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
void makeSound() {
System.out.println("Dog barks");
}
void fetch() {
System.out.println("Dog fetches");
}
}
public class TestDowncasting {
public static void main(String[] args) {
Animal animal = new Dog(); // Upcasting
Dog dog = (Dog) animal; // Explicit downcasting
dog.makeSound(); // Outputs "Dog barks"
dog.fetch(); // Outputs "Dog fetches"
// Unsafe downcasting that will cause a ClassCastException at runtime
Animal anotherAnimal = new Animal();
Dog anotherDog = (Dog) anotherAnimal; // Will throw ClassCastException
anotherDog.makeSound(); // This line will not be reached
}
}
Valid Casts:
Invalid Casts:
ClassCastException
will occur at runtime.Compiler-Time Errors: The Java compiler will catch casting errors between unrelated types because it can determine the type hierarchy at compile time.
Animal animal = new Animal();
String str = (String) animal; // Compiler error: Inconvertible types
Runtime Errors: The ClassCastException
is thrown when the cast is technically legal (from a superclass to a subclass) but fails at runtime because the object is not an instance of the target type.
Animal animal = new Animal();
Dog dog = (Dog) animal; // Runtime error: ClassCastException
instanceof
OperatorTo avoid ClassCastException
, you can use the instanceof
operator to check if the object is an instance of the target type before casting.
public class TestInstanceOf {
public static void main(String[] args) {
Animal animal = new Dog(); // Upcasting
if (animal instanceof Dog) {
Dog dog = (Dog) animal; // Safe downcasting
dog.makeSound(); // Outputs "Dog barks"
dog.fetch(); // Outputs "Dog fetches"
} else {
System.out.println("The object is not an instance of Dog.");
}
Animal anotherAnimal = new Animal();
if (anotherAnimal instanceof Dog) {
Dog anotherDog = (Dog) anotherAnimal; // Safe downcasting
anotherDog.makeSound();
} else {
System.out.println("The object is not an instance of Dog.");
}
}
}
instanceof
to check type compatibility.ClassCastException
occurs when an invalid downcast is performed.Understanding these concepts helps ensure type safety and proper usage of polymorphism in Java applications.