Java Tutorial
🔍

Java Type Casting

Sometimes you have a value of one type but need to use it as a different type.

A double balance that needs to be stored as an int. An int that needs to participate in a double calculation. A char that turns out to have a numeric value. These situations happen constantly in real Java programs.

Type casting is the mechanism Java provides to convert one data type into another.

👉 What you'll learn here:

  • ›The two kinds of type casting — widening and narrowing
  • ›When Java does it automatically vs when you must do it yourself
  • ›What data loss means and when it happens
  • ›How casting works with char
  • ›Common mistakes and how to avoid them

🧘 Type casting is simple once you understand the direction.

The only thing that matters is whether you're going from a smaller type to a bigger one (safe, automatic) or from a bigger type to a smaller one (risky, manual). Everything else follows from that.

Why Types Need Converting

Consider this:

int a = 10; int b = 3; double result = a / b; System.out.println(result); // prints 3.0 — NOT 3.333...

Even though result is declared as double, the division a / b happens between two int values first — producing integer 3. Then 3 is stored as 3.0.

To get the decimal result you expect, you need type casting:

double result = (double) a / b; System.out.println(result); // 3.3333333333333335 ✅

This is one of the most common beginner mistakes in Java — and type casting is the fix.

Two Kinds of Casting

TWO KINDS OF TYPE CASTING Widening (Automatic) Small type → Large type No data loss · Java does it for you int → double double result = 5; // 5.0 Safe — like pouring water into a bigger glass Narrowing (Manual) Large type → Small type May lose data · You must do it explicitly double → int int x = (int) 9.99; // 9 Risky — like pouring water into a smaller glass

💡 The water glass analogy: Widening casting is like pouring water from a small glass into a bigger one — nothing spills. Narrowing casting is like pouring water from a big glass into a smaller one — some water overflows and is lost.

Widening Casting — Automatic

Widening casting happens when you convert a smaller type to a larger type. Java does this automatically — no extra syntax required.

The order from smallest to largest:

byte → short → int → long → float → double

Any conversion moving left to right happens automatically:

int myInt = 100; long myLong = myInt; // int → long (automatic) float myFloat = myLong; // long → float (automatic) double myDouble = myFloat; // float → double (automatic) System.out.println(myInt); // 100 System.out.println(myLong); // 100 System.out.println(myFloat); // 100.0 System.out.println(myDouble); // 100.0

No data is lost — a larger container always fits the same value.

Common real-world example — int used in double calculation:

int price = 250; int quantity = 3; double total = price * quantity; // int × int = int → auto-widened to double System.out.println(total); // 750.0

Narrowing Casting — Manual

Narrowing casting happens when you convert a larger type to a smaller type. Because data can be lost, Java forces you to be explicit — you must write the cast yourself.

Syntax:

targetType variableName = (targetType) value;
double myDouble = 9.99; int myInt = (int) myDouble; // explicit cast required System.out.println(myDouble); // 9.99 System.out.println(myInt); // 9 ← decimal part is cut off

⚠️ Narrowing truncates, it does not round. The decimal portion is simply removed — not rounded to the nearest whole number.

int a = (int) 9.1; // 9 (not 9) int b = (int) 9.9; // 9 (NOT 10 — no rounding) int c = (int) -9.9; // -9 (NOT -10)

More narrowing examples:

double salary = 75999.99; int rounded = (int) salary; // 75999 — decimal dropped System.out.println(rounded); // 75999 long bigNumber = 1234567890123L; int smaller = (int) bigNumber; // may overflow — value corrupted System.out.println(smaller); // unpredictable result

The Type Casting Order

TYPE CASTING ORDER byte short int long float double → Widening (automatic) — no data loss ← Narrowing (manual cast required) — may lose data

Casting with char

char values have a numeric equivalent — their Unicode value. This means char can be cast to and from integer types.

char to int — get the Unicode number:

char letter = 'A'; int code = letter; // widening — automatic System.out.println(code); // 65 (Unicode value of 'A') char digit = '5'; int num = digit; System.out.println(num); // 53 (Unicode value of '5', NOT the number 5)

int to char — get the character for a Unicode number:

int code = 66; char letter = (char) code; // narrowing — manual cast System.out.println(letter); // B int code2 = 97; char letter2 = (char) code2; System.out.println(letter2); // a (lowercase a)

Useful pattern — iterate through alphabet:

for (int i = 65; i <= 90; i++) { System.out.print((char) i + " "); } // A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

💡 Key Unicode values to remember:

  • ›'A' = 65, 'Z' = 90
  • ›'a' = 97, 'z' = 122
  • ›'0' = 48, '9' = 57

Casting with Arithmetic — The Integer Division Trap

This is the most common type casting mistake in Java:

int a = 7; int b = 2; System.out.println(a / b); // 3 — integer division, decimal lost System.out.println((double) a / b); // 3.5 — cast a to double first System.out.println(a / (double) b); // 3.5 — cast b to double first System.out.println((double)(a / b)); // 3.0 — too late! division already happened

⚠️ The cast must happen BEFORE the division, not after. (double)(a / b) first does integer division (7/2 = 3), then converts 3 to 3.0 — the decimal is already lost.

Practical example — calculating a percentage:

int correct = 45; int total = 60; // Wrong: double percentage = correct / total * 100; System.out.println(percentage); // 0.0 — integer division gives 0, then × 100 = 0.0 // Correct: double percentage = (double) correct / total * 100; System.out.println(percentage); // 75.0 ✅

String Conversion — Not Casting, But Related

Converting between String and numeric types is not technically casting — Java provides specific methods for this. But beginners often look for it here, so it's included.

Number → String:

int num = 42; String text = String.valueOf(num); // "42" String text2 = Integer.toString(num); // "42" String text3 = "" + num; // "42" — simplest shorthand

String → Number:

String s = "123"; int num = Integer.parseInt(s); // 123 String d = "3.14"; double pi = Double.parseDouble(d); // 3.14

⚠️ Integer.parseInt() throws an exception if the String is not a valid number:

int x = Integer.parseInt("hello"); // ❌ NumberFormatException at runtime int x = Integer.parseInt("42"); // ✅ 42

Common Casting Mistakes

1. Forgetting to cast before integer division

double avg = 7 / 2; // ❌ 3.0 — integer division happened first double avg = (double) 7 / 2; // ✅ 3.5

2. Casting after division — too late

double result = (double)(10 / 3); // ❌ 3.0 — division already gave 3 double result = (double) 10 / 3; // ✅ 3.3333...

3. Expecting rounding instead of truncation

int x = (int) 9.9; // ❌ expecting 10 // ✅ actually 9 — truncation, not rounding

To round properly, use Math.round():

long rounded = Math.round(9.9); // 10 ✅ int rounded = (int) Math.round(9.9); // 10 ✅

4. Overflowing when narrowing large values

long big = 10000000000L; int small = (int) big; // ❌ overflow — result is unpredictable System.out.println(small); // 1410065408 (corrupted value)

Always check the value fits in the target type's range before narrowing.

5. Confusing char as a number

char c = '5'; int num = c; System.out.println(num); // 53 (Unicode of '5', NOT 5) // To get the actual digit value: int digit = c - '0'; // 53 - 48 = 5 ✅ System.out.println(digit); // 5

Quick Reference

ConversionDirectionAutomatic?Data Loss?Syntax
int → doubleWidening✅ Yes❌ Nodouble d = myInt;
double → intNarrowing❌ No✅ Yes (decimal)int i = (int) myDouble;
int → longWidening✅ Yes❌ Nolong l = myInt;
long → intNarrowing❌ No✅ Possibleint i = (int) myLong;
char → intWidening✅ Yes❌ Noint i = myChar;
int → charNarrowing❌ No✅ Possiblechar c = (char) myInt;
int → String—❌ No❌ NoString.valueOf(myInt)
String → int—❌ No❌ NoInteger.parseInt(myStr)

The 3 Things to Remember From This Page

  1. ›Widening is automatic, narrowing is manual — going from small to large type happens automatically. Going from large to small requires an explicit (type) cast.
  2. ›Narrowing truncates — it does not round — (int) 9.9 gives 9, not 10. Use Math.round() if you need rounding.
  3. ›Cast before dividing, not after — (double) a / b gives a decimal result. (double)(a / b) is too late — integer division already happened.

Summary

  • ›Type casting converts a value from one data type to another
  • ›Widening — small to large (int → double). Automatic, no data loss
  • ›Narrowing — large to small (double → int). Manual (type) cast required, may lose data
  • ›Narrowing truncates the decimal — it does not round
  • ›char has a Unicode numeric value — it widens automatically to int and narrows with (char)
  • ›Integer division trap — cast at least one operand to double before dividing, not after
  • ›String conversion uses String.valueOf(), Integer.parseInt(), Double.parseDouble() — not casting syntax

What to Read Next

Practice Programs

Put this topic into practice — each program has full code, output and a step-by-step explanation you can run online.

Browse all Java programs →