Object Oriented Programming with JavaUnit 139 min read
Type Conversion & Casting: Implicit, Explicit, and Object Casting
Unit 13 of Object Oriented Programming with Java covers type conversion (primitive and object), casting rules, widening/narrowing conversions, and their applications in real-world Java programs, with visual traces of how values change during operations.
TAKEAWAYS:
- Understand the difference between implicit (automatic) casting and explicit (manual) casting in Java.
- Know when widening (upcasting) and narrowing (downcasting) conversions are needed, and their risks.
- Master object casting (upcasting/downcasting) in inheritance hierarchies, including
instanceofchecks. - Recognize autoboxing/unboxing for primitive-wrapper conversions and their performance implications.
- Apply type conversion in real scenarios like financial calculations, sensor data processing, or game physics.
- Avoid common pitfalls like loss of precision or classcast exceptions in casting operations.
Core Concepts: Primitive Type Conversion
1. Primitive Data Type Hierarchy
Java primitives have an implicit ordering for casting:
byte → short → int → long → float → double
char → int (via Unicode value)
graph LR
A["byte"] --> B["short"]
B --> C["int"]
C --> D["long"]
D --> E["float"]
E --> F["double"]
G["char"] --> CWhy this matters: Only conversions up this hierarchy (widening) are implicit. Downward (narrowing) requires explicit casting.
2. Implicit (Widening) Conversion
Automatic conversion when storing a smaller type in a larger one. No data loss.
Example: Storing int in double:
int num = 10;
double d = num; // Implicit conversion
Trace:
| Variable | Type | Value (binary) | Notes |
|---|---|---|---|
num |
int |
000...0001010 |
Original value |
d |
double |
0.0...10.0 |
Automatically widened |
Real-world use:
- eSewa transaction processing: When converting
int(transaction ID) toStringfor logging or display. - Ncell billing system: Converting
float(call duration in minutes) todoublefor precise billing calculations.
3. Explicit (Narrowing) Conversion
Manual conversion when storing a larger type in a smaller one. Risk of data loss.
Example: Storing double in int:
double pi = 3.14159;
int truncatedPi = (int) pi; // Explicit casting
Trace:
| Variable | Type | Value (binary) | Notes |
|---|---|---|---|
pi |
double |
3.14159... |
Original value |
truncatedPi |
int |
000...0001100001 |
Precision lost! (3) |
Visualization of Loss:
Real-world caution:
- NEPSE stock price updates: If you cast
double(share price) tointfor display, fractional pence/paise are lost, misleading investors. - Pathao fare calculation: Rounding
float(distance) toint(meters) for fare tiers can undercharge users.
Object Casting in OOP
4. Upcasting and Downcasting
- Upcasting: Child → Parent (implicit, safe).
- Downcasting: Parent → Child (explicit, risky).
Example: Animal hierarchy
class Animal {}
class Dog extends Animal {}
Animal a = new Dog(); // Upcasting (implicit)
Dog d = (Dog) a; // Downcasting (explicit)
Trace of Downcasting:
graph TD
A["Animal a = new Dog()"] --> B["Dog d = (Dog) a"]
B -->|"Success"| C["Dog methods work"]
B -->|"Fail"| D["ClassCastException"]Real-world use:
- Khalti payment gateway: Upcasting
PaymenttoDigitalPaymentto process all digital transactions uniformly. - Daraz order queue: Downcasting
OrdertoFoodOrderto apply restaurant-specific delivery rules.
5. instanceof Operator
Checks if an object can be cast safely before downcasting.
if (a instanceof Dog) {
Dog d = (Dog) a; // Safe downcast
}
Trace:
Object (a) |
instanceof Dog |
Action |
|---|---|---|
new Dog() |
true |
Downcast succeeds |
new Cat() |
false |
Avoids ClassCastException |
Real-world use:
- NTC network traffic: Checking if a
Packetis anAudioPacketbefore processing with codec-specific logic.
Autoboxing and Unboxing
6. Primitive-Wrapper Conversions
Automatic conversion between primitives and their wrapper classes (e.g., int ↔ Integer).
Integer num = 10; // Autoboxing (int → Integer)
int primitive = num; // Unboxing (Integer → int)
Trace:
| Variable | Type | Value | Notes |
|---|---|---|---|
num |
Integer |
Integer(10) |
Autoboxed from int |
primitive |
int |
10 |
Unboxed back to primitive |
Performance Note:
- Autoboxing adds overhead. Avoid in performance-critical loops (e.g., game physics).
Real-world use:
- Bank loan calculators: Storing
int(loan term in months) asIntegerin collections for dynamic resizing. - YouTube video buffering: Using
Double(buffer progress %) for smooth UI updates.
Common Pitfalls and Best Practices
7. Comparison Table: Conversion Types
| Type | Example | Safety | Use Case |
|---|---|---|---|
| Implicit (Widening) | int → double |
Safe | Math operations, scaling |
| Explicit (Narrowing) | double → int |
Unsafe | Truncation, memory optimization |
| Upcasting | Dog → Animal |
Safe | Polymorphism, APIs |
| Downcasting | Animal → Dog |
Risky | Feature-specific logic |
| Autoboxing | int → Integer |
Generally safe | Collections, generics |
8. When Things Go Wrong
Precision Loss:
double salary = 1234567.89; int intSalary = (int) salary; // Loses 0.89Fix: Use
Math.round()orBigDecimalfor financial data.ClassCastException:
Object obj = "Hello"; Integer num = (Integer) obj; // Throws exception!Fix: Use
instanceofchecks.Autoboxing Overhead:
// Slow for large loops for (int i = 0; i < 1000000; i++) { Integer boxed = i; // Autoboxing in loop }Fix: Use primitives in performance-critical code.
Worked Example: Traffic Light Timer (Real-World Scenario)
Problem: Simulate a traffic light cycle with int (seconds) and String (light color). Use casting to handle transitions.
class TrafficLight {
private int duration;
private String color;
public TrafficLight(int duration, String color) {
this.duration = duration;
this.color = color;
}
public void changeLight() {
if (color.equals("RED")) {
duration = (int) (duration * 0.8); // Narrowing: double → int
color = "GREEN";
} else {
color = "RED";
}
}
}
Trace:
| Step | duration (Type) |
color (Type) |
Notes |
|---|---|---|---|
| Initial | 60 (int) |
"RED" |
Start of cycle |
After changeLight() |
48 (int) |
"GREEN" |
Duration reduced (narrowing) |
| Next cycle | 48 (int) |
"RED" |
Color toggled |
Real-world tie-in:
- Kathmandu traffic management: Adjusting light durations dynamically based on sensor data (e.g.,
floatsensor input →inttimer value).
Exam Tip
Spot the Conversion:
- Questions often hide conversions in arithmetic or method calls. Example:
Answer:double result = 10 / 3; // What’s the result? (3.0 vs 3?)3.0(implicitint→doubleconversion).
- Questions often hide conversions in arithmetic or method calls. Example:
Casting Tricks:
- Watch for
instanceofin downcasting questions. Always check before casting. - Example:
if (obj instanceof String) { String s = (String) obj; // Safe }
- Watch for
Common Exam Patterns:
- Trace tables: Draw a table showing variable types/values before/after conversion.
- Error identification: Given code, predict where
ClassCastExceptionor precision loss occurs. - Real-world scenarios: Expect questions like:
"A bank calculates interest as
double. If stored in anintvariable, what’s the risk?" Answer: Loss of fractional paise, leading to incorrect interest calculations.
Code Snippets:
- Memorize the syntax for:
- Explicit casting:
(type) value instanceofchecks- Autoboxing/unboxing examples
- Explicit casting:
- Memorize the syntax for:
Diagrams:
- Draw the primitive hierarchy or inheritance tree with upcast/downcast arrows when asked to explain casting.
Final Visual Summary:
mindmap
root((Type Conversion in Java))
Primitive
Widening
byte → short → int → long → float → double
Narrowing
Risk of precision loss
Object
Upcasting
Child → Parent (implicit)
Downcasting
Parent → Child (explicit, needs instanceof)
Autoboxing
int ↔ Integer
Performance overhead
Pitfalls
ClassCastException
Precision lossBased on the TU BIM syllabus for Object Oriented Programming with Java (IT234), unit 13.
Discussion
Loading…