Firas
Posted on February 22, 2024
I’ve compiled a list of questions and answers about fundamental topics in Java that I believe every Java developer should be aware of. This is part 1, covering the concepts of type-casting, upcasting and downcasting.
What is type-casting?
it refers to the process of converting from one data type to another.
What are the conditions for type-casting?
To convert between data types:
- the data types must be compatible. We can convert an integer to a float or vice versa, but we can't convert between an integer and a String. A compile error will be thrown in this case.
- The data type that we convert into must be larger than the original data type. Otherwise, Java will complain. However, this is still possible with a workaround, which we will discuss in the next section.
What are the categories of type-casting?
There are two types of type-casting:
-
Widening conversion (implicit casting): If we cast a smaller data type to a larger one, Java compiler will automatically perform the casting. For example, if we want to convert from an integer to a double, we only need to assign the integer value to a double because integers are smaller (32 bits) than doubles (64 bits), so there is no risk of data loss after conversion. Here's a code snippet to demonstrate this:
double number = 10; //output = 10.0, which is a double
We declared a double variable and assigned to it an integer value of
10
. Since an integer is smaller than a double, the double will easily have more than enough room to store that value. -
Narrowing conversion (explicit casting): If we cast a larger data type to a smaller one, Java compiler will complain and will not perform the conversion. For instance, attempting to cast a double to an integer will trigger a compile error. To solve this, we can explicitly cast the value to the smaller data type using the casting operator ():
int number = (int) 10.50; //output = 10, which is an integer
Contrary to the previous example, the double value of
10.50
is assigned to an integer. Without an explicit operator, a portion of data would be lost since it's larger than what an integer can hold. So we use the casting operator(int)
next to the double value so that it gets converted and stored as an integer.Type-casting with primitive types vs reference types
type-casting not only works works on primitive types, but on reference types as well, although in slightly different ways due to the inherent difference between primitive and reference type variables.
What is Upcasting?
Upcasting is a process of implicitly casting a subclass to a superclass. It is closely related to inheritance.
Before we further discuss this, let's look an example:
public class Vehicle {
private String name;
public Vehicle() {}
public void driveVehicle() {
System.out.println("vehicle");
}
}
public class Car extends Vehicle {
private String model;
public Car() {
super();
}
public void driveCar() {
System.out.println("car");
}
public String getModel() {
return model;
}
}
As you can see, there are two classes, Vehicle and Car. The Car class extends or inherits Vehicle. In this scenario, when we create an object of type Car, we can either assign it to a reference of type Car class like so:
Car car = new Car();
Or assign it to a reference of type Vehicle, which is the superclass:
Vehicle car = new Car();
This is an example of upcasting where the compiler implicitly casts the subclass to the superclass.
Using upcasting, we can access all methods defined in the superclass from the subclass but we're restricted from calling the methods in the sublcass itself.
If we attempt to call a method in the subclass based on the last example, the compiler will complain:
Vehicle vehicle = new Car();
// vehicle.getModel(); Cannot resolve method 'getModel' in 'Vehicle'
What is Downcasting?
Downcasting is the reverse of upcasting. It’s a process of casting from the superclass to subclass.
Let’s modify the previous example:
// Upcasting
Vehicle vehicle = new Car();
// Downcasting
if(vehicle instanceof Vehicle) {
Car car = (Car) vehicle;
car.driveCar();
}
We use instanceof
to check if the vehicle
reference is an instance of Vehicle
class before explicitly downcasting using the (Car)
operator. This is a way to prevent ClassCastException
at runtime.
Downcasting is particularly useful in cases where we have an instance of a superclass but we need to use the fields and methods of a subclass. Since we can only access superclass fields and methods in this scenario, downcasting is an approach to solve this problem.
There you have it. This is part one of the series of Java questions and answers. I hope what we've discussed so far was helpful. Stay tuned for part two.
Posted on February 22, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.