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:
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:
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
💡 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:
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.0No data is lost — a larger container always fits the same value.
Common real-world example — int used in double calculation:
1int price = 250;
2int quantity = 3;
3double total = price * quantity; // int × int = int → auto-widened to double
4
5System.out.println(total); // 750.0Narrowing 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:
1targetType variableName = (targetType) value;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.
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:
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 resultThe Type Casting Order
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:
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:
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:
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:
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:
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:
1int num = 42;
2String text = String.valueOf(num); // "42"
3String text2 = Integer.toString(num); // "42"
4String text3 = "" + num; // "42" — simplest shorthandString → Number:
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:
1int x = Integer.parseInt("hello"); // ❌ NumberFormatException at runtime
2int x = Integer.parseInt("42"); // ✅ 42Common Casting Mistakes
1. Forgetting to cast before integer division
1double avg = 7 / 2; // ❌ 3.0 — integer division happened first
2double avg = (double) 7 / 2; // ✅ 3.52. Casting after division — too late
1double result = (double)(10 / 3); // ❌ 3.0 — division already gave 3
2double result = (double) 10 / 3; // ✅ 3.3333...3. Expecting rounding instead of truncation
1int x = (int) 9.9; // ❌ expecting 10
2 // ✅ actually 9 — truncation, not roundingTo round properly, use Math.round():
1long rounded = Math.round(9.9); // 10 ✅
2int rounded = (int) Math.round(9.9); // 10 ✅4. Overflowing when narrowing large values
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
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); // 5Quick Reference
| Conversion | Direction | Automatic? | Data Loss? | Syntax |
|---|---|---|---|---|
int → double | Widening | ✅ Yes | ❌ No | double d = myInt; |
double → int | Narrowing | ❌ No | ✅ Yes (decimal) | int i = (int) myDouble; |
int → long | Widening | ✅ Yes | ❌ No | long l = myInt; |
long → int | Narrowing | ❌ No | ✅ Possible | int i = (int) myLong; |
char → int | Widening | ✅ Yes | ❌ No | int i = myChar; |
int → char | Narrowing | ❌ No | ✅ Possible | char c = (char) myInt; |
int → String | — | ❌ No | ❌ No | String.valueOf(myInt) |
String → int | — | ❌ No | ❌ No | Integer.parseInt(myStr) |
The 3 Things to Remember From This Page
- ›Widening is automatic, narrowing is manual — going from small to large type happens automatically. Going from large to small requires an explicit
(type)cast. - ›Narrowing truncates — it does not round —
(int) 9.9gives9, not10. UseMath.round()if you need rounding. - ›Cast before dividing, not after —
(double) a / bgives 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
- ›
charhas a Unicode numeric value — it widens automatically tointand narrows with(char) - ›Integer division trap — cast at least one operand to
doublebefore dividing, not after - ›String conversion uses
String.valueOf(),Integer.parseInt(),Double.parseDouble()— not casting syntax
What to Read Next
| Topic | Link |
|---|---|
| Data types and their ranges | Data Types → |
| Variables — declaration and initialization | Variables → |
| Operators — arithmetic and integer division | Operators → |
| Strings — conversion and manipulation | String Basics → |
| Exception handling — NumberFormatException | Exception Handling → |