Type Casting in Java: What Is Casting in Java and How to Use It Effectively in 2025
By Arjun Mathur
Updated on Jan 09, 2025 | 23 min read | 12.91K+ views
Share
All Courses
For working professionals
Doctorate
Artificial Intelligence
MBA
Data Science
Marketing
Management
Education
Law
For fresh graduates
Software & Tech
Data Science
Management
Marketing
Back
Doctorate
View All Doctorate Courses
Artificial Intelligence
View All AI Courses
Data Science
View All Data Science Courses
Marketing
View All Marketing Courses
Management
View All Management Courses
Education
View all Education Courses
Software & Tech
View All Software & Tech Courses
Data Science
View All Data Science Courses
Management
View All Management Courses
Marketing
View All Marketing Courses
More
By Arjun Mathur
Updated on Jan 09, 2025 | 23 min read | 12.91K+ views
Share
Table of Contents
Type Casting in Java is a fundamental concept that allows you to convert one data type into another, either explicitly or implicitly. Whether you're working with primitives or objects, understanding how to use type casting in Java effectively can help you write more efficient and error-free code.
In this guide, you’ll learn the two main types of casting: widening (automatic) and narrowing (explicit), explore real-world examples, and uncover best practices for using casting safely.
By the end, you'll know how to handle conversions between data types, avoid runtime errors, and optimize your Java programs for 2025 and beyond. Let's dive into the details and make type casting work for you!
Let’s face it—Java is all about handling data in the most efficient and error-free way possible. Type casting Java code is crucial for managing data compatibility during operations like arithmetic calculations, data assignments, and object interactions. It’s what lets you adapt data types to fit specific requirements, optimizing memory usage and program performance.
For example:
Let’s explore two main types of type casting Java code:
1. Primitive Type Casting
When dealing with primitive types, type casting Java code becomes unavoidable. Let’s say you want to assign an int value to a double variable. This is called widening casting and happens automatically because there’s no risk of data loss. On the flip side, when you’re converting a double back to an int, it’s narrowing casting, and Java requires you to explicitly cast it because some data might be lost.
Example:
public class Main { public static void main(String[] args) { int num = 10; double bigNum = num; // Widening casting double pi = 3.14; int roundedPi = (int) pi; // Narrowing casting System.out.println("Widening casting: int to double - " + bigNum); System.out.println("Narrowing casting: double to int - " + roundedPi); } } Output:
Widening casting: int to double - 10.0 Narrowing casting: double to int - 3Software Development Courses to upskill
Explore Software Development Courses for Career Progression
Explanation:
By understanding these mechanics, you can ensure proper and safe use of typecasting in your Java applications.
2. Object Type Casting
Type casting Java code isn’t just about numbers—it’s also essential when working with objects, especially in inheritance and polymorphism. Imagine you have a Vehicle class and a Car subclass. To access Car-specific features from a Vehicle reference, you’d need to perform downcasting.
Example:
// Base class class Vehicle { public void start() { System.out.println("Vehicle is starting..."); } } // Subclass class Car extends Vehicle { public void playMusic() { System.out.println("Playing music in the car..."); } } public class Main { public static void main(String[] args) { // Upcasting: A Car object is treated as a Vehicle Vehicle myCar = new Car(); myCar.start(); // Calls the start method from Vehicle class // Downcasting: Converting Vehicle reference back to a Car reference if (myCar instanceof Car) { // Check to ensure the object is of type Car Car specificCar = (Car) myCar; specificCar.start(); // Calls the start method from Vehicle class specificCar.playMusic(); // Calls the playMusic method from Car class } else { System.out.println("Downcasting is not safe for this object."); } } } Output:
Vehicle is starting... Vehicle is starting... Playing music in the car...Explanation:
This ability to cast between objects ensures you can take full advantage of polymorphism and dynamic behavior in your programs.
Also Read: What is Upcasting and Downcasting in Java? Simple Explanation
Here are some real-world scenarios for type casting Java code:
By understanding and effectively using typecasting in Java, you’ll avoid errors, handle data more flexibly, and write programs that are both efficient and robust.
Now that you understand the importance of typecasting in Java, let’s clarify what casting entails and the role it plays in Java programming
Casting in Java is the process of converting data from one type to another to ensure compatibility. It applies to both primitive types (e.g., converting int to double) and object types (e.g., downcasting from a parent class to a subclass).
To better understand what is casting in Java, let’s explore its two categories:
Understanding both implicit and explicit casting will help you unlock the ability to manage data effectively across various scenarios in Java programming.
Also Read: Top 8 Reasons Why Java Is So Popular and Widely Used in 2025
Casting is essential in Java for ensuring seamless compatibility between different data types, enhancing program efficiency, and preventing errors.
Casting is a key tool for writing flexible and robust Java programs. For example, when processing an API response that returns data as Object, casting it into a specific type like String or Integer ensures the data is usable in your program.
Modern Java versions, particularly from Java 10 onward, introduce several features that simplify typecasting and reduce the need for explicit casting in common scenarios. These features include type inference with var, records for structured data modeling, and enhancements to functional programming with the Stream API, which can also help avoid explicit casting.
Example:
Subscribe to upGrad's Newsletter
Join thousands of learners who receive useful tips
// Import necessary packages import java.util.List; public class ModernJavaFeaturesDemo { public static void main(String[] args) { // Using var for type inference var numbers = List.of(1, 2, 3.5, "text"); // Inferred as List<Object> // Stream API for functional processing with mixed types numbers.stream() .filter(obj -> obj instanceof Number) // Filter out non-numeric elements .map(obj -> ((Number) obj).doubleValue()) // Convert to double .forEach(System.out::println); // Print each double value // Using pattern matching for instanceof Object obj = "Java"; if (obj instanceof String str) { System.out.println("String value: " + str.toUpperCase()); } // Using records for simplified data modeling record Point(double x, double y) {} var point = new Point(2.5, 4.0); System.out.println("Point coordinates: " + point.x() + ", " + point.y()); } } Output:
1.0 2.0 3.5 STRING VALUE: JAVA Point coordinates: 2.5, 4.0 1.0 2.0 3.5Explanation:
This code showcases how modern Java features work together to simplify typecasting, functional programming, and structured data handling, while ensuring clean and efficient code. It reduces boilerplate, improves readability, and demonstrates practical real-world applications.
Also Read: 45+ Best Java Project Ideas for Beginners in 2025 with Source Code & Best Practices
With a clear understanding of what is casting in Java, it’s time to explore its two primary forms—widening and narrowing—and how they impact data conversion.
Typecasting in Java can be categorized into two main types: widening casting and narrowing casting. These conversions help Java handle data types of different sizes and precision smoothly.
This is the automatic conversion of smaller data types into larger ones, performed by Java when there’s no risk of data loss. It’s simple and requires no extra effort from the programmer.
Key Points:
Code Example:
public class WideningCastingExample { public static void main(String[] args) { int smallNum = 42; double bigNum = smallNum; // Implicit widening casting System.out.println(bigNum); } } Output:
42.0 Explanation: Widening casting automatically converts smaller data types (int) to larger ones (double) without any explicit instruction. This ensures precision is preserved and avoids data loss.
Want to dive deeper into the aspects of Java and enhance your programming knowledge? Check out this free upGrad course on Java basics!
Also Read: Java Architecture & Components Explained
This is the manual conversion of larger data types into smaller ones. Since this can lead to data loss, Java requires explicit instructions from the programmer.
Key Points:
Code Example:
public class NarrowingCastingExample { public static void main(String[] args) { double bigNum = 42.56; int smallNum = (int) bigNum; // Explicit narrowing casting System.out.println(smallNum); } } Output:
42 Understanding these two types of conversions will help you confidently handle diverse data types in your programs, ensuring compatibility and efficient memory use.
Typecasting, while useful, can affect performance, especially in large-scale applications or runtime-critical scenarios. Here's a comparison of widening and narrowing typecasting to illustrate their performance impact:
Aspect | Widening Typecasting | Narrowing Typecasting |
| Definition | Converts a smaller type to a larger type (e.g., int to long). | Converts a larger type to a smaller type (e.g., double to int). |
| Type of Casting | Implicit (automatic by the JVM). | Explicit (requires programmer-defined casting). |
| Performance Impact | Negligible; no data loss or complex operations. | Slightly higher; involves truncation or precision adjustment. |
| Data Loss | None, as the value remains intact. | Possible, especially when converting floating-point to integers. |
| Example | int small = 42; long large = small; | double large = 42.99; int small = (int) large; |
| Runtime Efficiency | Ideal for high-frequency operations with minimal overhead. | Slower due to additional validation and truncation by the JVM. |
| Best Use Case | Frequently used in runtime-critical scenarios or data processing. | Avoided in loops or high-throughput scenarios unless absolutely necessary. |
To better understand the implications, let’s look at an example code:
public class TypecastingPerformance { public static void main(String[] args) { long startTime, endTime; // Widening typecasting performance startTime = System.nanoTime(); for (int i = 0; i < 1_000_000; i++) { double widened = i; // Implicit cast } endTime = System.nanoTime(); System.out.println("Widening Typecasting Time: " + (endTime - startTime) + " ns"); // Narrowing typecasting performance startTime = System.nanoTime(); for (double i = 0; i < 1_000_000; i++) { int narrowed = (int) i; // Explicit cast } endTime = System.nanoTime(); System.out.println("Narrowing Typecasting Time: " + (endTime - startTime) + " ns"); } } Output:
Widening Typecasting Time: 3,000 ns Narrowing Typecasting Time: 15,000 nsExplanation of the Code:
Widening typecasting is faster and suitable for runtime-critical tasks, whereas narrowing typecasting has higher overhead and should be minimized in performance-sensitive scenarios.
Also Read: 15 Essential Java Full Stack Developer Skills
Understanding widening and narrowing casting is foundational, but Java also defines a hierarchy that governs how data types interact. Let’s explore how this hierarchy helps ensure seamless typecasting.
The hierarchy of typecasting in Java defines how data types and objects can be converted from one form to another while maintaining compatibility. This hierarchy is fundamental to understanding how primitive types and objects interact within Java’s type system.
In Java, primitive types follow a well-defined hierarchy for widening (implicit) casting:
byte → short → int → long → float → double For objects, the hierarchy is based on class inheritance:
Also Read: Types of Inheritance in Java: Single, Multiple, Multilevel & Hybrid
When dealing with interfaces:
Below is a simple representation of the typecasting hierarchy for primitive types and objects:
Primitive Hierarchy:
byte → short → int → long → float → double Object Hierarchy:
Object ↑ Superclass ↑ Subclass (Explicit Downcasting) Knowing these relationships will help you understand exactly when and how to apply type casting in Java, ensuring your programs handle data and objects efficiently.
Also Read: Serializable Interface in Java with Examples
Beyond primitive types, typecasting in Java is equally powerful for objects and interfaces. Here’s how it facilitates inheritance and polymorphism.
When working with objects and interfaces in Java, casting is crucial for enabling dynamic behavior and ensuring type compatibility. By leveraging inheritance and interfaces, you can write more flexible and reusable code.
Let’s break it down step by step:
Upcasting is the process of converting a subclass object into its superclass type. This is an implicit conversion and is often used to enable polymorphism in Java.
Why Upcasting?
Example Code:
class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { void sound() { System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal myDog = new Dog(); // Upcasting myDog.sound(); // Polymorphism in action } } Output:
Dog barksExplanation: Upcasting allows a Dog object to be treated as an Animal. During runtime, the overridden sound() method in Dog is called, demonstrating polymorphism.
Downcasting is the reverse of upcasting: converting a superclass reference back into a subclass type. Unlike upcasting, downcasting must be explicit and carries risks like ClassCastException if the object isn’t actually an instance of the subclass.
How to Prevent Risks?
Example Code:
class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { void sound() { System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal myAnimal = new Dog(); // Upcasting if (myAnimal instanceof Dog) { // Type check Dog myDog = (Dog) myAnimal; // Downcasting myDog.sound(); // Calls Dog's sound method } else { System.out.println("Not a Dog instance"); } } } Output:
Dog barks Explanation: Downcasting explicitly converts a superclass reference (Animal) to a subclass (Dog). The instanceof check ensures type safety, preventing ClassCastException. Here, the downcast allows access to Dog's specific implementation of sound(
Casting becomes essential when dealing with arrays and collections, especially when working with generic types or heterogeneous data.
1. Casting with Arrays
public class Main { public static void main(String[] args) { Object[] objects = new String[3]; // Upcasting objects[0] = "Hello"; String str = (String) objects[0]; // Downcasting System.out.println(str); // Output: Hello } } Output:
Hello Explanation: The Object[] reference is cast back to String to access its specific functionality.
2. Casting with Collections
import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList<Object> list = new ArrayList<>(); // Mixed types list.add("Java"); list.add(123); String text = (String) list.get(0); // Downcasting int number = (int) list.get(1); // Downcasting System.out.println(text); System.out.println(number); } } Output:
Java 123 Explanation: The elements of the collection are stored as Object types, requiring explicit casting to access specific types.
Also Read: A Complete ArrayList in Java: What You Need to Know
Learning object and interface casting will not only help you unlock the power of polymorphism and dynamic method invocation but also set the stage for effectively leveraging typecasting in Java in real-world applications.
Typecasting in Java remains essential in modern Java applications, especially when working with frameworks like Spring, Hibernate, or JSON libraries. Below are real-world scenarios where typecasting plays a critical role:
1. JSON Parsing and API Integration
When integrating APIs, JSON data often needs to be parsed into Java objects. Libraries like Jackson or Gson handle most type conversions automatically, but custom typecasting is required for complex or nested data.
Example:
// Import necessary packages import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Map; public class JsonParsingExample { public static void main(String[] args) throws Exception { // JSON string representing API response String json = "{ \"id\": 1, \"value\": \"example\" }"; // ObjectMapper is a library class used to convert JSON to Java objects ObjectMapper objectMapper = new ObjectMapper(); // Parse JSON into a Map where keys and values are dynamic var map = objectMapper.readValue(json, Map.class); // Typecast specific fields from the Map int id = (int) map.get("id"); // Cast to int for numeric field String value = (String) map.get("value"); // Cast to String for text field // Print the parsed and casted values System.out.println("ID: " + id + ", Value: " + value); } } Output:
ID: 1, Value: exampleExplanation:
Why It Matters: Custom typecasting in Java ensures data integrity when dealing with dynamically typed JSON responses.
2. ORM Frameworks (e.g., Hibernate)
In Hibernate, entities are often mapped to database tables. Typecasting ensures that fields in the database align with Java types, especially for custom data types or when working with projections.
Example:
// Import necessary Hibernate packages import org.hibernate.query.Query; import org.hibernate.Session; public class HibernateTypecastingExample { public static void main(String[] args) { // Open a Hibernate session to interact with the database Session session = HibernateUtil.getSessionFactory().openSession(); // Query returning a projection (selected fields instead of full entity) Query<Object[]> query = session.createQuery("SELECT e.id, e.name FROM Employee e", Object[].class); // Get the results as a list of Object arrays var results = query.list(); // Iterate through each result for (Object[] row : results) { int id = (int) row[0]; // Cast first element to int (Employee ID) String name = (String) row[1]; // Cast second element to String (Employee Name) System.out.println("ID: " + id + ", Name: " + name); } // Close the session session.close(); } } Output:
ID: 101, Name: John Doe ID: 102, Name: Jane SmithExplanation:
Why It Matters: Projections often return arrays of Object, requiring typecasting to extract meaningful data.
3. Spring Framework Use Cases
In Spring, typecasting is commonly used in methods like getBean or when working with generics in dependency injection.
Example:
// Import necessary Spring packages import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class SpringTypecastingExample { public static void main(String[] args) { // Initialize Spring ApplicationContext with configuration ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // Retrieve a bean by its name and typecast to the expected class MyService service = (MyService) context.getBean("myService"); // Call a method on the retrieved bean service.performTask(); } } // Service class class MyService { public void performTask() { System.out.println("Task performed!"); } } // Configuration class class AppConfig { @Bean public MyService myService() { return new MyService(); } } Output:
Task performed!upGrad’s Exclusive Software and Tech Webinar for you –
SAAS Business – What is So Different?
Explanation:
Why It Matters: Typecasting ensures that retrieved beans match the expected types, avoiding runtime errors.
Typecasting plays a vital role in modern Java development, especially in frameworks like Spring, Hibernate, and libraries for JSON parsing. Understanding these use cases ensures efficient and error-free application development.
However, while its benefits are substantial, improper usage can introduce significant challenges and errors. Let’s look at common pitfalls and how to avoid them.
Type casting Java code is powerful, but it comes with its challenges. Misuse can lead to errors, data loss, and reduced code quality. Here’s a breakdown of common pitfalls and best practices to help you use type casting safely and effectively:
Common Pitfalls | Description |
| ClassCastException | Occurs when an invalid downcasting is attempted, leading to runtime errors. |
| Potential Data Loss in Narrowing Conversions | Data may be truncated when converting larger types (e.g., double) to smaller ones (e.g., int). |
| Reduced Code Readability Due to Excessive Casting | Excessive or unnecessary casting makes code harder to read and maintain. |
Here’s a list of best practices that will help you avoid the common pitfalls:
Best Practices | Strategy |
| Use instanceof for Safe Downcasting | Always check the type with instanceof before downcasting to avoid ClassCastException. |
| Leverage Generics to Minimize Runtime Casting | Generics enforce type safety at compile time, reducing the need for runtime casting. |
| Validate Ranges During Narrowing Conversions | Before performing narrowing casting, ensure the value is within the target type’s range. |
Here are some examples of best practices:
Using instanceof:
class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { void bark() { System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal myAnimal = new Dog(); // Upcasting if (myAnimal instanceof Dog) { Dog myDog = (Dog) myAnimal; // Safe downcasting myDog.bark(); // Calls Dog-specific method } } } Output:
Dog barks Explanation: The instanceof check ensures the Animal reference is safely downcast to Dog, avoiding runtime errors and enabling access to subclass-specific methods.
Using Generics:
public class Main { public static void main(String[] args) { double bigNum = 150.56; if (bigNum <= Integer.MAX_VALUE && bigNum >= Integer.MIN_VALUE) { int smallNum = (int) bigNum; // Safe narrowing conversion System.out.println(smallNum); } } } Output:
150Explanation: Range validation ensures the double value fits within the integer range, preventing data loss or overflow during narrowing conversion.
Validating Ranges:
public class Main { public static void main(String[] args) { double bigNum = 150.56; if (bigNum <= Integer.MAX_VALUE && bigNum >= Integer.MIN_VALUE) { int smallNum = (int) bigNum; // Safe narrowing conversion System.out.println(smallNum); } } } Following these best practices will help you ensure your type casting is safe, efficient, and contributes to cleaner, more maintainable code.
Also Read: Java Full Stack Developer Roadmap
Once you’ve mastered the basics and avoided common pitfalls, it’s time to delve into advanced typecasting techniques to tackle more complex scenarios.
As you grow in your Java development journey, mastering advanced type casting techniques is essential for writing robust, efficient, and error-resistant programs. Let’s dive into these sophisticated approaches and see how they’re applied in modern Java:
When casting objects, there’s always a risk of a ClassCastException if the object’s type doesn’t match the expected type. Proper exception handling mechanisms can help manage this gracefully. It ensures your program doesn’t crash when a casting error, like ClassCastException, occurs.
Example:
public class Main { public static void main(String[] args) { try { Object obj = "Java"; // String object Integer num = (Integer) obj; // Unsafe cast, throws ClassCastException } catch (ClassCastException e) { System.out.println("Invalid casting attempt: " + e.getMessage()); } } } Output:
Invalid casting attempt: java.lang.String cannot be cast to java.lang.Integer Explanation:
Best Practice: Use exception handling sparingly. Validate types with instanceof to minimize reliance on try-catch blocks.
Also Read: Exception Handling in Java [With Examples]
Generics are a powerful tool for enforcing type safety at compile time, reducing the need for runtime casting. They make your code cleaner and prevent errors before they occur.
Example Without Generics:
import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList list = new ArrayList(); // No generics list.add("Java"); String str = (String) list.get(0); // Requires casting System.out.println(str); } }Output:
Java Example With Generics:
import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); // Generics list.add("Java"); String str = list.get(0); // No casting needed System.out.println(str); // Output: Java } } Output:
Java Explanation:
Generics eliminate ambiguity, making your code more reliable and easier to maintain.
Dynamic type casting is performed when the type of an object is determined at runtime. This often involves using the instanceof operator for safe type checking before casting.
Example:
public class Main { public static void main(String[] args) { Object obj = "Hello, Java!"; if (obj instanceof String) { // Type checking String str = (String) obj; // Safe dynamic casting System.out.println("String value: " + str); } else { System.out.println("Object is not a String"); } } } Output:
String value: Hello, Java!Explanation:
Dynamic casting is particularly useful when working with APIs, frameworks, or other situations where object types might not be known beforehand.
By incorporating these advanced techniques, you’ll handle type casting challenges with confidence, writing programs that are both error-resistant and future-proof.
Also Read: Careers in Java: How to Make a Successful Career in Java in 2025
Mastering typecasting, from basics to advanced techniques, is a crucial skill for Java developers. If you’re looking to deepen your understanding, structured courses can provide the guidance needed to excel.
Mastering Java and its nuances, like type casting, is essential for a thriving career in software development.
upGrad’s specialized courses offer in-depth technical knowledge, practical hands-on experience, and access to a library of 100+ free courses. Join a thriving community of over 1 million learners and gain job-ready skills to confidently address real-world industry challenges.
Here are some different types of business management courses that you can enrol for:
Course Title | Description |
| Best Full Stack Developer Bootcamp 2024 | A program designed to equip learners with essential skills in both front-end and back-end development, preparing them for successful careers in software engineering. |
| Java Object-oriented Programming | Master the fundamentals of Object-Oriented Programming (OOP) in Java with this free course, and learn key concepts like classes, inheritance, and polymorphism. |
| JavaScript Basics from Scratch | This free course offers a comprehensive introduction to fundamental programming concepts and web development skills using JavaScript. |
| Master of Design in User Experience | Earn a Master’s in User Experience Design from Jindal School of Art and Architecture, and gain expertise in creating intuitive, user-centered designs for digital products. |
Also, get personalized career counseling with upGrad to shape your programming future, or you can visit your nearest upGrad center and start hands-on training today!
Boost your career with our popular Software Engineering courses, offering hands-on training and expert guidance to turn you into a skilled software developer.
Master in-demand Software Development skills like coding, system design, DevOps, and agile methodologies to excel in today’s competitive tech industry.
Stay informed with our widely-read Software Development articles, covering everything from coding techniques to the latest advancements in software engineering.
Implicit casting (widening) happens automatically, while explicit casting (narrowing) requires manual intervention using the cast operator.
Yes, data loss can occur during narrowing conversions (e.g., double to int) as the fractional part is truncated.
No, final variables cannot be modified, so type casting doesn’t apply to their reassignment.
Java automatically converts primitives to their wrapper classes (autoboxing) and vice versa (unboxing), but explicit casting may still be required for certain operations.
Java throws a ClassCastException at runtime if you attempt to cast an object to an incompatible type.
Yes, arrays can be upcasted and downcasted, but caution is needed to avoid runtime exceptions if the array contains incompatible types.
Type casting introduces slight overhead due to runtime checks, especially in object casting, but it’s generally negligible in most scenarios.
Type casting is often unnecessary in method overriding since the JVM resolves the method call dynamically based on the object’s runtime type.
Yes, generics and type-safe APIs reduce the need for explicit casting by enforcing compile-time type safety.
It’s possible but risky. Without instanceof, you may encounter a ClassCastException if the object isn’t of the expected type.
No, Java doesn’t allow casting between classes that don’t share an inheritance relationship, as they are fundamentally incompatible.
57 articles published
Arjun Mathur is Program Marketing Manager for the Software Development, bringing over 5+ years of experience in ed‑tech and growth marketing. A B.Tech in Computer Engineering from IIT Delhi, he specia...
Top Resources