Upcasting and downcasting in Java Tutorial

In this section, we will learn what the upcasting and downcasting is and how to use it in Java.

What is casting in Java?

Casting is about changing the type of one object and treating it as if it’s of another type. Casting occurs between types (classes) that are in relation to each other. For example, two classes can run casting if there’s a parent-child relation between them.

Types of Casting in Java

There are two types of casting in Java:

  • Upcasting (widening)
  • Downcasting (Narrowing)

Upcasting in Java

Up-casting happens anytime we create an object from a subclass and store the reference of that object in a variable of type parent class.

When a class inherits from another one, we can be rest assured that the sub-class at least behaves the same as the base class. This means the sub-class will have the same members as what the parent class has already.

Example: upcasting in Java

Create a class named Machine and put the code below into that file:

public class Machine {
    public void start(){
        System.out.println("Machine started!");
    }
}

Now create another class named `Camera` and put the code below into that file:

public class Camera extends Machine {
    @Override
    public void start(){
        System.out.println("Camera started!");
    }
    public void shot(){
        System.out.println("Taking a shot");
    }
}

This class inherits from the `Machine` class and it also overrode the `start` method. Other than the `start()` method, it has another method named `shot()` as well.

Now create the third class named `Simple` and put the code below into that file:

public class Simple {
    public static void main(String[] args) {
        Machine machine = new Machine();
        Camera camera = new Camera();
        machine.start();
        camera.start();
        camera.shot();
    }
}

Output:

Machine started!

Camera started!

Taking a shot

As you can see, two objects of type `Machine` and `Camera` are created respectively and both objects have the access to the `start()` method. The object that is created from the `Camera` has one more method `shot()` but at its core, it has the same behavior as the `Machine` class because both have the same method which is `start()`.

Because of this fact, in Java we can create an object from subclasses and store the reference of that object into a variable of type parent class.

Example:

Refactor the `Simple` class in the example above to match this source code:

public class Simple {
    public static void main(String[] args) {
        Machine machine = new Camera();
        machine.start();
    }
}

Output:

Camera started!

Note: The important note to remember here is that, when upcasting, only those members of the parent class are accessible. For example, here we couldn’t use the `start` method via the `machine` variable. Because the `machine` variable is of type `Machine` and in this class, there’s no method with the name `shot`. So check the type of the variable that stores the reference to the object and any member defined in that class, we can access them in the object.

Downcasting in Java

Down casting is about storing the reference of an object that is created from a parent class in a variable of type sub-class.

In short, this is not allowed in Java! Take the last example: A camera is always guaranteed to be a machine, but a machine is not always a camera!

Example: downcasting in Java

public class Simple {
    public static void main(String[] args) {
        Camera camera = new Machine();
        camera.start();
    }
}

Output:

Error:(5, 25) java: incompatible types: tuto.Machine cannot be converted to tuto.Camera

Here we’ve got compile time error.

This is because:

When using the assignment `=` operator to store the reference of an object into a variable, the compiler will check the type of the right side of the operator. If the type was compatible with the type of the left-hand operator, then the assignment is allowed.

Compatible here means: either the right side type should be exactly the same as the left side operator (both of the same class). Or the type of the object should be a subclass of the class that we set as the type of the variable on the left side.

In the example above, the type on the right side of the assignment `=` operator is `Machine`. This type is neither the same as the type of the left side class nor it’s a subclass of the `Camera` class.

For this reason, the compiler won’t allow the assignment and so we get the error.

But here there’s a way that we can convince the compiler that the type of the object at the right side of the operator at runtime will be something else that is compatible with the type of the left side variable.

This is called explicit casting.

Take the example below:

public class Simple {
    public static void main(String[] args) {
        Camera camera = (Camera) new Machine();
        camera.start();
    }
}

Output:

Exception in thread "main" java.lang.ClassCastException: class tuto.Machine cannot be cast to class tuto.Camera

As you can see, we’ve used the pair of the parentheses on the left side of the object to convince the compiler that the type is (or will be) the `Camera` class. So the compiler gives a green light here and we’re headed towards runtime.

Here we’ve surpassed the compile time error checking, but at runtime we still got an error and the program crashed.

Because at runtime still the type of the object will be checked again to see if it matches the type of the variable that is going to store the reference of this object. Because these two types are not compatible, we got runtime exception.

Now you might be asking, then where can we use this down casting?

Well, take the example below:

public class Simple {
    public static void main(String[] args) {
        Machine machine = new Camera();
        Camera camera = (Camera) machine;
        camera.start();
        camera.shot();
    }
}

Output:

Camera started!

Taking a shot

Check this statement:

Camera camera = (Camera) machine;

Here we know the object that the `machine` variable is referring to, at runtime, will be the object which is created from `Camera` class type, right? But that is runtime and in compile time the compiler does not know this fact and if we try to assign the value of the `machine` variable into the `camera` variable, it will only check the type of these two variables. The compiler does not care what value is about to be sent from right side to the left side of the assignment operator.

So what we can do here is to use the explicit casting to convince the compiler that at runtime, types will match and there won’t be any type error.

This is where we can and should use explicit casting.

Java instanceof operator

There is a keyword named `instanceof` that we can use to check the type of object against a class and see if the type of the object matches the class. It will return true if they match and false otherwise. Please check the Java instanceof section to learn more about this keyword and see how it helps in down casting situations.

Facebook
Twitter
Pinterest
LinkedIn

Top Technologies