Upcasting and downcasting in Java - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
We want to understand how the time it takes to run code changes when using upcasting and downcasting in Java.
Specifically, we ask: does casting affect how long the program runs as the input size grows?
Analyze the time complexity of the following code snippet.
class Animal { }
class Dog extends Animal { void bark() {} }
public class Main {
public static void main(String[] args) {
Animal[] animals = new Dog[1000];
for (int i = 0; i < animals.length; i++) {
animals[i] = new Dog(); // upcasting
}
for (Animal a : animals) {
Dog d = (Dog) a; // downcasting
d.bark();
}
}
}
This code creates an array of Dogs stored as Animals (upcasting), then converts each back to Dog (downcasting) to call a Dog method.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Two loops each running through the array of animals.
- How many times: Each loop runs once over all elements, so 1000 times in this example.
As the number of animals grows, the loops run more times, so the work grows proportionally.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 operations (2 loops x 10) |
| 100 | About 200 operations |
| 1000 | About 2000 operations |
Pattern observation: The total work grows directly with the number of elements, doubling the input doubles the work.
Time Complexity: O(n)
This means the time to run the code grows in a straight line with the number of elements processed.
[X] Wrong: "Casting objects takes extra loops or slows down the program significantly."
[OK] Correct: Casting is a simple check or reference change done once per object, it does not add extra loops or big work as input grows.
Understanding how casting fits into time complexity helps you explain performance clearly and shows you know what parts of code affect speed.
"What if we added a nested loop inside the downcasting loop to check each Dog against all others? How would the time complexity change?"
Practice
Upcasting means:Solution
Step 1: Understand object type hierarchy
In Java, classes can inherit from other classes, making some types more general (superclass) and others more specific (subclass).Step 2: Define upcasting
Upcasting means treating a subclass object as if it were an instance of its superclass, which is more general.Final Answer:
Treating a specific object as a more general type -> Option BQuick Check:
Upcasting = Treat specific as general [OK]
- Confusing upcasting with downcasting
- Thinking upcasting creates a new object
- Believing upcasting changes the actual object type
Animal a = new Dog(); // Downcast here
Solution
Step 1: Understand downcasting syntax
Downcasting requires an explicit cast to convert a superclass reference back to a subclass type.Step 2: Apply correct cast
The correct syntax is:SubclassType var = (SubclassType) superClassVar;so here:Dog d = (Dog) a;Final Answer:
Dog d = (Dog) a; -> Option AQuick Check:
Downcasting needs explicit cast [OK]
- Omitting the cast operator
- Casting to wrong type
- Using methods like toDog() which don't exist
class Animal { void sound() { System.out.println("Animal sound"); } }
class Dog extends Animal { void sound() { System.out.println("Bark"); } void fetch() { System.out.println("Fetching"); } }
public class Test {
public static void main(String[] args) {
Animal a = new Dog(); // upcasting
a.sound();
// a.fetch(); // line A
((Dog) a).fetch(); // line B
}
}Solution
Step 1: Understand method overriding and upcasting
Variableais of type Animal but refers to a Dog object. Callinga.sound()calls Dog's overridden method, printing "Bark".Step 2: Analyze method call fetch()
Methodfetch()is not in Animal, soa.fetch()is invalid (commented out). Downcasting(Dog) aallows callingfetch(), printing "Fetching".Final Answer:
Bark Fetching -> Option AQuick Check:
Upcast calls overridden method, downcast calls subclass method [OK]
- Thinking a.sound() calls Animal's method
- Trying to call fetch() without downcasting
- Confusing compile vs runtime errors
class Animal {}
class Cat extends Animal { void meow() { System.out.println("Meow"); } }
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
Cat c = (Cat) a; // line X
c.meow();
}
}Solution
Step 1: Identify the casting problem
Variablearefers to an Animal object, not a Cat. Casting Animal to Cat without checking causes ClassCastException at runtime.Step 2: Fix with instanceof check
Before casting, checkif (a instanceof Cat)to ensure safe downcasting and avoid runtime error.Final Answer:
ClassCastException at runtime; fix by checking instanceof before casting -> Option CQuick Check:
Downcast only if instanceof true [OK]
- Ignoring runtime ClassCastException
- Assuming cast always works
- Trying to fix with syntax changes only
class Vehicle { void start() { System.out.println("Vehicle started"); } }
class Car extends Vehicle { void start() { System.out.println("Car started"); } void openTrunk() { System.out.println("Trunk opened"); } }
class Bike extends Vehicle { void start() { System.out.println("Bike started"); } void kickStart() { System.out.println("Kickstarted"); } }Which code snippet correctly upcasts and downcasts to call
openTrunk() safely?Solution
Step 1: Understand upcasting and downcasting here
Variablevis declared as Vehicle but assigned a Car object (upcasting). To call Car-specific methodopenTrunk(), downcast is needed.Step 2: Check safe downcasting
Usinginstanceofensuresvis actually a Car before downcasting and callingopenTrunk(). This avoids runtime errors.Final Answer:
Vehicle v = new Car(); if (v instanceof Car) { ((Car) v).openTrunk(); } -> Option DQuick Check:
Upcast then instanceof check before downcast [OK]
- Downcasting without instanceof check
- Assigning superclass object to subclass variable
- Calling subclass methods on superclass references without cast
