Type Casting in Java with Examples

type-casting.jpg

In Java, type casting simply means converting a value from one data type to another. It might sound technical at first, but it’s something you do all the time, often without even realizing it. Let’s dive deeper.

Table of Contents:

What is Type Casting in Java?

Java is a strongly typed language, which means the type of every variable must be known at compile time. That’s great for catching bugs early, but it also means you have to be a little more deliberate when switching between types. That’s where type casting comes into use. 

Let’s define type casting in Java: it’s the process of converting a value from one data type to another. Imagine that you’re working with both int and double values in a calculation. Java needs both values to be of the same type to do the math properly. If they’re not, it quietly converts one of them behind the scenes. That’s type casting in action.


Type Casting helps in:

  • Reusing variables across different operations
  • Interacting with methods that expect a specific type
  • Preventing unexpected behavior in calculations or logic

Types of Type Casting in Java

Type casting in Java is not a one-size-fits-all operation. There are two main types, and each serves a different purpose depending on what you’re trying to convert and how safe or automatic that conversion is.

1. Widening Type Casting (Implicit)

Widening or implicit type casting in Java is when Java automatically converts a smaller data type into a larger one. For example, turning an int into a long, or a float into a double. Since there’s no risk of losing information in these cases, Java takes care of it quietly, behind the scenes.

This kind of casting is safe and doesn’t need any special syntax. You just assign the smaller type to a larger one, and Java handles the rest.


Example:

int num = 42;
double result = num;  // int is automatically cast to double

2. Narrowing Type Casting (Explicit)

Narrowing or explicit type casting in Java is the opposite: it’s when you convert a larger data type into a smaller one. This can lead to loss of precision or unexpected behavior, so Java doesn’t do it automatically. You have to tell it what you’re doing, using parentheses.


Example:

double score = 89.75;
int roundedScore = (int) score;  // You must cast explicitly

Here, the decimal portion is dropped, and roundedScore ends up being just 89.

Since narrowing can trim off data or even change the value, it’s something you want to use with care. One mistyped cast can quietly create a bug that’s tough to track down.

Widening Type Casting (Implicit)

Widening type casting in Java is when you convert a smaller data type into a larger one. Imagine that you are pouring water from a small cup into a bigger one; nothing spills, and the transition is smooth. 

What Makes It “Widening”?

In Java, data types have a sort of built-in hierarchy based on size and precision. For primitives, the order generally looks like this:

byte → short → int → long → float → double

So if you assign an int to a long, or a float to a double, Java knows it’s a safe move. No data will be lost, and no cast is needed.

Example: int to double

Java

Output:

int to double

Here, Java quietly converts the int value 25 into a double. You didn’t need to write any special syntax; Java just knew what to do.

Why Use Widening Casting?

Most of the time, widening casting just happens. You’ll see it in calculations where different types are involved:

int score = 90;
double average = score / 2.0;  // score is widened to double

This ensures the result is a floating-point number instead of being rounded down to an integer.

Narrowing Type Casting (Explicit)

Narrowing type casting is a bit more hands-on. It happens when you try to convert a larger data type into a smaller one. Unlike widening, Java won’t do this automatically; you have to explicitly tell it what to do. Why? Because narrowing can be risky. You might lose data, precision, or even end up with unexpected results.

When Does Narrowing Happen?

Picture this: you’re trying to fit a gallon of water into a coffee mug. That’s what narrowing casting is like; the data might not fit neatly. For example, converting a double to an int means chopping off the decimal part.

That’s why Java makes you cast it manually using parentheses.

Example: double to int

Java

Output:

double to int

In this case, the decimal portion is just gone. No rounding, just a hard cut. That’s why narrowing needs your permission.

Syntax of Narrowing

It’s simple but very deliberate:

dataType variableName = (targetType) value;

Another example:

long largeNum = 100000L;
short shortNum = (short) largeNum;

If largeNum is too big to fit into a short, Java won’t complain during compilation, but the value might wrap around or behave unpredictably at runtime.

1. What Can Go Wrong?

Here are a few pitfalls to watch for:

  • Precision loss: Decimals are dropped when casting from float or double to int, short, or byte.
  • Overflow: If the number is too large to fit in the target type, the result wraps around, causing weird outputs.
  • Truncation: Casting from a floating-point number to an integer always cuts off the decimal, not round.
float f = 123.99f;
byte b = (byte) f;
System.out.println(b);  // Might not be what you expect

Narrowing gives you control, but with great power comes great responsibility. Make sure you understand the trade-offs when shrinking data types, as you might introduce bugs that are hard to track otherwise.

Type Casting Between Non-Primitive (Reference) Types

So far, we have looked at type casting between primitive types like int, double, and float. But what about when you’re working with objects? This is where reference type casting comes in.

In Java, all classes are part of a hierarchy. That means one class can be a subclass (child) or superclass (parent) of another. You can cast objects up or down this hierarchy depending on the situation.

Let’s break it down.

1. Upcasting (Implicit)

Upcasting means converting a subclass type into a superclass type. This is safe and automatic, and Java handles it for you without complaint.

class Animal {}
class Dog extends Animal {}
Dog dog = new Dog();
Animal pet = dog;  // Upcasting: Dog → Animal

Here, dog is automatically treated as an Animal. This is useful when writing flexible, reusable code (like working with collections of animals instead of individual species).

2. Downcasting (Explicit)

Downcasting is the reverse; you’re trying to treat a parent object as a more specific child type. Since not all Animal objects are actually Dogs, Java makes you cast explicitly, and even then, it’s risky.

Animal pet = new Dog();  // Upcast
Dog buddy = (Dog) pet;   // Downcast (safe because pet is actually a Dog)

If the object isn’t actually an instance of the target class, you’ll get a ClassCastException at runtime.

3. When Casting Goes Wrong

Let’s look at a case that compiles fine but crashes when you run it:

Animal pet = new Animal();  // Just a plain Animal
Dog buddy = (Dog) pet;      // This will throw an error

Why? Because pet isn’t really a Dog, so Java can’t magically turn it into one.

4. Pro Tip: Use instanceof to Stay Safe

Before downcasting, it’s good practice to check what the object really is:

if (pet instanceof Dog) {
    Dog buddy = (Dog) pet;
    buddy.bark();
}

This avoids runtime crashes and keeps your code safer and cleaner.

Object casting can be powerful, especially when working with polymorphism, inheritance, or generic collections. Just remember: always know what your object really is before casting it around.

Difference Between Type Casting and Type Conversion

Beginners often confuse type conversion and type casting in Java to be the same thing. While they are similar and are used to convert data types, they function differently under the hood. Having a strong understanding of the difference between them will enable you to make better decisions when implementing them in your own code.

AspectType Conversion (Widening)Type Casting (Narrowing)
Performed byJava (automatic)Programmer (manual)
SyntaxNo cast neededRequires explicit cast (int)
Data loss riskNonePossible
Exampleint x = 10; double y = x;double d = 9.9; int x = (int) d;

Type Conversion

Type conversion typically refers to what Java does for you. It’s automatic, safe, and happens during operations where two data types are involved.

Java

Output:

Type Conversion
  • The integer x is automatically converted to a double without any explicit casting.
  • This is safe because a double has a wider range and higher precision than an int.

No fuss, no warnings, no syntax tricks. Java just makes it work.

Type Casting

Type casting, on the other hand, is manual and requires specific syntax to implement. You’re telling Java that it might not be 100% safe, but to go ahead and convert it anyway.

Java

Output:

Type Casting
  • The double value 9.99 is explicitly cast to an int.
  • The decimal portion is truncated, not rounded. So 9.99 becomes 9.
  • This is a classic case of data loss in narrowing conversions.

You are losing data here as the decimal part is dropped. Java won’t stop you, but it makes sure you take responsibility by requiring the cast.

Common Mistakes While Type Casting in Java

Even though type casting can seem like a simple topic, it is important to avoid a few common mistakes that can lead to unexpected behaviour or even runtime crashes.

Let’s walk through the ones you should watch out for.

1. Data Loss in Narrowing Conversions

When you cast from a larger numeric type to a smaller one, Java does not throw an error. However, it will quietly chop off any part of the value that doesn’t fit.

Java

Output:

Data Loss in Narrowing Conversions

Here, the decimal portion is lost completely. It is not rounded, just discarded.

In other cases, the number might not fit into the target type at all. That can cause a value wraparound.

Java

Output:

wraparound

This happens because byte can only hold values between -128 and 127. The cast works syntactically, but the result is not what most developers expect.

2. ClassCastException at Runtime

Casting between object types is where many developers get caught. Java allows explicit downcasting between related classes, but if the actual object does not match the expected type, the code will compile but fail at runtime.

Animal animal = new Animal();
Dog dog = (Dog) animal;  // Throws ClassCastException

Although Animal and Dog are part of the same hierarchy, the actual object here is not a Dog. Java will throw a ClassCastException the moment you run this code.

3. Ignoring Arithmetic Promotion Rules

In numeric expressions, Java may promote types based on the operation. If you’re not careful about the order or placement of type casting, you can get results that look wrong but are technically correct.

Java

Output:

Ignoring Arithmetic Promotion Rules

You might expect 2.5, but integer division happens first, then the result is cast to double. To fix this, cast before the division:

Java

Output:

cast before the division

4. Assuming All Casting Is Safe

Just because two types look related does not mean they can be cast freely. For instance, Java will not allow casting between completely unrelated classes.

String text = "123";
// int num = (int) text;  // Compile-time error

In such cases, casting is not the answer. Use parsing instead:

int num = Integer.parseInt(text);

5. How to Avoid These Errors

  • Use instanceof before downcasting any object.
  • Be mindful of the range of values when narrowing primitive types.
  • When in doubt, test and log the output after casting.
  • Never assume a cast will work just because the code compiles.

Best Practices for Safe Type Casting in Java

Type casting in Java can be useful, but if not implemented correctly, it could lead to a lot of confusion as well. Here are some best practices to keep in mind when implementing typecasting in your own code. 

1. Know Your Data Before You Cast

Before you try to cast a value, be sure to understand what kind of data type you are working with. Are you casting a double that might lose its decimal part? Are you downcasting an object that may not be what you think it is? Having a clear picture of the kind of data will help you choose the optimal approach.

2. Always Use instanceof Before Downcasting

Whenever you are working with objects, especially in class hierarchies, it is never safe to assume that type casting will just work. It is always recommended that you use the instanceof operator to check the object’s type before forcing it into a new one.

if (animal instanceof Dog) {
    Dog dog = (Dog) animal;
    dog.bark();
}

Without this check, you could run into a ClassCastException at runtime, which can crash your program and be hard to debug.

3. Avoid Unnecessary Casting

Adding casting just because you can will clutter up your code. Before you cast, ask yourself. Is this the right approach? Java is pretty smart with type promotion in most cases, so don’t try to outsmart the compiler unless you have a reason.

int x = 10;
double result = x / 2.0;  // No need to cast x

4. Be Extra Cautious with Narrowing

Any time you convert from a larger type to a smaller one, like double to int or long to short, double-check whether the value will fit. If there’s any chance of overflow or loss of precision, it’s worth rethinking your approach or adding a validation check.

5. Always Test Edge Cases

It’s easy to test your cast with safe values. But what happens if you cast 128 into a byte, or a null reference into an object? Test with values that are near the upper and lower limits of what your target type can handle.

Type Casting in Java Examples

When you are just starting out in Java, type casting can seem like an abstract topic. You must be wondering, “A few numbers are converted, so what?”, or “Where does this actually matter in the real world?”. Type casting can be found everywhere in Java. It quietly supports a lot of what we do when we build Java applications. Let’s look at some type casting in Java examples:

1. Reading Numbers from a File or User Input

Let’s say that you are working with data from a user form where all the inputs are Strings, and you need numbers to work with. Casting is a good approach to solve this problem.

Java

Output:

Reading Numbers from a File or User Input

Without this conversion, you won’t be able to perform any mathematical operations on the value. This is extremely common in form handling, CLI programs, or reading CSV data.

2. UI Rendering: Double to Int

When working with UI components like coordinates or pixel size, you will often need to cast a double into an int. 

Java

Output:

UI Rendering

UI frameworks typically expect integers, so this kind of narrowing cast is very common in GUI development.

3. APIs and Object Casting

When working with libraries, frameworks, or generic APIs, you will often get generic objects as a response, and you’ll need to cast them into the type that you require.

Object obj = getFromAPI();
if (obj instanceof Employee) {
    Employee emp = (Employee) obj;  // Safe downcast
    System.out.println(emp.getSalary());
}

This is common in situations involving polymorphism, abstract factories, or frameworks like Spring, where the method returns a base type or interface.

4. Arithmetic Precision in Financial Apps

One of the most obvious use cases of casting in Java is in scientific and financial applications. It helps you ensure that you are working with floating-point numbers whenever needed.

Java

Output:

Arithmetic Precision in Financial Apps

Without casting, you will get a 2 instead of 2.5, which, as you know, can be a critical mistake in financial applications.

Conclusion

In this blog, we have defined type casting in Java, its types, common errors, and even real-world examples. From understanding how widening and narrowing work, to safely casting between objects using instanceof, you’ve now got a solid grasp of how and when to use type casting in your Java programs. Type casting in Java is an essential addition to your Java programming arsenal that is used in many Java applications. If you want to learn more about Java development, check out our Java certification program, where we dig deeper into more Java topics such as data types, type erasures,  and even classes and objects.

FAQs – Java Type Casting

1. What is the difference between type conversion and type casting in Java

Type conversion is done automatically in Java. It happens when Java promotes a smaller data type into a larger one.

int num = 5;
double result = num;  // implicit conversion

Type casting, on the other hand, is manual and requires explicit syntax when converting a larger data type into a smaller one, which can lead to data loss.

double score = 9.99;
int rounded = (int) score;  // manual casting
2. What is ClassCastException in Java? When does it occur, and how can you avoid it?

ClassCastException in Java is a runtime error that occurs when you try to cast an object into a subclass to which it is not an instance of.

Animal animal = new Animal();
Dog dog = (Dog) animal;  // Throws ClassCastException

Use the instanceof operator to avoid ClassCastException by checking the object type before casting

3. Can you cast between any two types in Java?

No, in Java, you can only cast between compatible types. For primitive types, casting works when there’s a valid widening or narrowing path (like int to float, or double to byte).
For object types, the classes must share an inheritance relationship; otherwise, Java won’t allow it, and you’ll get a compile-time error.

4. Does casting affect performance in Java?

For most cases, casting in Java does not affect performance. But, unnecessary or unsafe casting, especially between objects, can lead to runtime errors and difficulty in debugging. So, it is recommended that you keep casting meaningful and minimal.

About the Author

Technical Research Analyst - Full Stack Development

Kislay is a Technical Research Analyst and Full Stack Developer with expertise in crafting Mobile applications from inception to deployment. Proficient in Android development, IOS development, HTML, CSS, JavaScript, React, Angular, MySQL, and MongoDB, he’s committed to enhancing user experiences through intuitive websites and advanced mobile applications.

Full Stack Developer Course Banner