Java Tutorial
🔍

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:

Java
1int a = 10; 2int b = 3; 3double result = a / b; 4 5System.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:

Java
1double result = (double) a / b; 2System.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:

Java
1int myInt = 100; 2long myLong = myInt; // int → long (automatic) 3float myFloat = myLong; // long → float (automatic) 4double myDouble = myFloat; // float → double (automatic) 5 6System.out.println(myInt); // 100 7System.out.println(myLong); // 100 8System.out.println(myFloat); // 100.0 9System.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:

Java
1int price = 250; 2int quantity = 3; 3double total = price * quantity; // int × int = int → auto-widened to double 4 5System.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:

Java
1targetType variableName = (targetType) value;
Java
1double myDouble = 9.99; 2int myInt = (int) myDouble; // explicit cast required 3 4System.out.println(myDouble); // 9.99 5System.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.

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

More narrowing examples:

Java
1double salary = 75999.99; 2int rounded = (int) salary; // 75999 — decimal dropped 3System.out.println(rounded); // 75999 4 5long bigNumber = 1234567890123L; 6int smaller = (int) bigNumber; // may overflow — value corrupted 7System.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:

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

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

Java
1int code = 66; 2char letter = (char) code; // narrowing — manual cast 3System.out.println(letter); // B 4 5int code2 = 97; 6char letter2 = (char) code2; 7System.out.println(letter2); // a (lowercase a)

Useful pattern — iterate through alphabet:

Java
1for (int i = 65; i <= 90; i++) { 2 System.out.print((char) i + " "); 3} 4// 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:

Java
1int a = 7; 2int b = 2; 3 4System.out.println(a / b); // 3 — integer division, decimal lost 5System.out.println((double) a / b); // 3.5 — cast a to double first 6System.out.println(a / (double) b); // 3.5 — cast b to double first 7System.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:

Java
1int correct = 45; 2int total = 60; 3 4// Wrong: 5double percentage = correct / total * 100; 6System.out.println(percentage); // 0.0 — integer division gives 0, then × 100 = 0.0 7 8// Correct: 9double percentage = (double) correct / total * 100; 10System.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:

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

String → Number:

Java
1String s = "123"; 2int num = Integer.parseInt(s); // 123 3 4String d = "3.14"; 5double pi = Double.parseDouble(d); // 3.14

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

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

Common Casting Mistakes

1. Forgetting to cast before integer division

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

2. Casting after division — too late

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

3. Expecting rounding instead of truncation

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

To round properly, use Math.round():

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

4. Overflowing when narrowing large values

Java
1long big = 10000000000L; 2int small = (int) big; // ❌ overflow — result is unpredictable 3System.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

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

Quick Reference

ConversionDirectionAutomatic?Data Loss?Syntax
intdoubleWidening✅ Yes❌ Nodouble d = myInt;
doubleintNarrowing❌ No✅ Yes (decimal)int i = (int) myDouble;
intlongWidening✅ Yes❌ Nolong l = myInt;
longintNarrowing❌ No✅ Possibleint i = (int) myLong;
charintWidening✅ Yes❌ Noint i = myChar;
intcharNarrowing❌ No✅ Possiblechar c = (char) myInt;
intString❌ No❌ NoString.valueOf(myInt)
Stringint❌ 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

TopicLink
Data types and their rangesData Types →
Variables — declaration and initializationVariables →
Operators — arithmetic and integer divisionOperators →
Strings — conversion and manipulationString Basics →
Exception handling — NumberFormatExceptionException Handling →
Type Casting | DevStackFlow