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
💡 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.0No 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.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:
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 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:
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 shorthandString → 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"); // ✅ 42Common 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.52. 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 roundingTo 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); // 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
Learn the symbols Java uses to perform calculations and comparisons.
Practice Programs
Put this topic into practice — each program has full code, output and a step-by-step explanation you can run online.
Parses text into an int with Integer.parseInt, handling input that isn't a valid number.
Shows the two meanings of char-to-int conversion: a character's code versus a digit's numeric value.
Compares three common ways of turning an int into a String and checks that they agree.
Calculates the average of an array's elements.
Divides one fixed integer by another and prints the result.
Converts a temperature from Celsius to Fahrenheit using the standard formula.
Computes what percentage one value is of another, such as marks obtained out of total marks.