Java Tutorial

Operators

Flow Control

String

Number and Date

Built-in Classes

Array

Class and Object

Inheritance and Polymorphism

Exception Handling

Collections, Generics and Enumerations

Reflection

Input/Output Stream

Annotation

Java Object Type Conversion: Upcasting And Downcasting

In Java, object type conversion (also called casting) is the process of converting an object from one class type to another. This tutorial covers the basics of object type conversion in Java, including upcasting, downcasting, and the instanceof operator.

  • Upcasting:

Upcasting is converting a reference of a subclass type to a superclass type. Upcasting is always safe and performed automatically by the Java compiler because a subclass object is also an instance of its superclass.

Example:

class Animal {
    public void makeSound() {
        System.out.println("Some sound...");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Animal animal = dog; // Upcasting from Dog to Animal
        animal.makeSound(); // Output: Woof!
    }
}
  • Downcasting:

Downcasting is converting a reference of a superclass type to a subclass type. Downcasting is not automatically performed by the Java compiler because it can lead to runtime errors if the object is not an instance of the target subclass. You must perform an explicit type cast to perform downcasting.

Example:

class Animal {
    // ...
}

class Dog extends Animal {
    public void bark() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();
        Dog dog = (Dog) animal; // Downcasting from Animal to Dog
        dog.bark(); // Output: Woof!
    }
}
  • The instanceof operator:

The instanceof operator is used to check if an object is an instance of a specific class or one of its subclasses. It's particularly useful for safely performing downcasting because you can verify the object's type before performing the cast.

Example:

class Animal {
    // ...
}

class Dog extends Animal {
    // ...
}

class Cat extends Animal {
    // ...
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();

        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            System.out.println("This animal is a Dog.");
        } else if (animal instanceof Cat) {
            Cat cat = (Cat) animal;
            System.out.println("This animal is a Cat.");
        } else {
            System.out.println("This animal is neither a Dog nor a Cat.");
        }
    }
}

In this tutorial, we discussed the basics of object type conversion in Java, including upcasting, downcasting, and the instanceof operator. Understanding how to use these concepts effectively is crucial for working with inheritance and polymorphism in your Java applications.

  1. Upcasting and Downcasting in Java with Examples:

    • Upcasting is casting to a more general type, while downcasting is casting to a more specific type.
    // Upcasting
    Animal animal = new Dog();
    
    // Downcasting
    if (animal instanceof Dog) {
        Dog dog = (Dog) animal;
        // Perform operations specific to Dog
    }
    
  2. Upcasting in Java and Its Use Cases:

    • Upcasting is useful when you want to treat objects of a subclass as objects of their superclass, facilitating polymorphism.
    Animal animal = new Dog(); // Upcasting
    
  3. Downcasting in Java with instanceof:

    • Downcasting checks the compatibility of an object's type before casting to avoid ClassCastException.
    Animal animal = new Dog();
    if (animal instanceof Dog) {
        Dog dog = (Dog) animal; // Downcasting
    }
    
  4. Java Casting Between Primitive Types and Objects:

    • Primitive types can be cast to their corresponding wrapper classes, and vice versa.
    int intValue = 42;
    Integer integerValue = (Integer) intValue; // Boxing (Auto or Manual)
    
  5. Polymorphism and Casting in Java:

    • Polymorphism allows treating objects of different types uniformly, often achieved through upcasting and method overriding.
    Animal animal = new Dog();
    animal.makeSound(); // Calls Dog's makeSound if overridden
    
  6. Covariant Return Types and Casting in Java:

    • Covariant return types enable returning a subtype in a subclass's overridden method.
    class Animal {
        Animal reproduce() { return new Animal(); }
    }
    
    class Dog extends Animal {
        @Override
        Dog reproduce() { return new Dog(); } // Covariant return type
    }
    
  7. Java Casting Exceptions and Handling:

    • Casting can throw ClassCastException if the types are incompatible. Using instanceof helps avoid exceptions.
    if (animal instanceof Dog) {
        Dog dog = (Dog) animal; // Downcasting with instanceof check
    } else {
        // Handle the case when casting is not possible
    }
    
  8. Java Casting with Interfaces:

    • Casting with interfaces is similar to casting with classes. It allows treating objects as instances of their implemented interfaces.
    interface Shape { /*...*/ }
    
    class Circle implements Shape { /*...*/ }
    
    Shape shape = new Circle();
    
  9. Java Generics and Type Casting:

    • Generics provide type safety, reducing the need for explicit casting in collections and methods.
    List<String> strings = new ArrayList<>();
    strings.add("Hello");
    String str = strings.get(0); // No casting needed