Type Casting and Type Conversion
Pouring water from a small glass into a big jug is safe; nothing spills. Pouring a full jug into a small glass is risky; some water ends up on the floor. Converting numbers between types works the same way. Going from a smaller type to a bigger one is safe, so Java does it for you. Going from bigger to smaller can lose data, so Java makes you say so explicitly with a cast.
Widening and Narrowing
| Widening (implicit) | Narrowing (explicit cast) | |
|---|---|---|
| Direction | Smaller type → bigger type | Bigger type → smaller type |
| Who does it | Java, automatically | You, by writing (type) |
| Risk | None for whole numbers | Decimals cut off, or the value wraps around |
| Example | double d = 450; | int i = (int) 99.99; |
Widening: Automatic
public class Widening {
public static void main(String[] args) {
int fare = 450;
long bigFare = fare;
double exactFare = fare;
System.out.println(bigFare + " and " + exactFare);
}
}450 and 450.0Lines 4 and 5 copy an int into a long and a double. Every int value fits in both, so no cast is needed.
Narrowing: You Must Cast
Going the other way without a cast is a compile error:
Narrow.java:4: error: incompatible types: possible lossy conversion from double to int
int rupees = price;
^Writing the target type in brackets, a cast, tells the compiler "I know data may be lost":
public class Narrowing {
public static void main(String[] args) {
double price = 99.99;
int rupees = (int) price;
System.out.println("Rupees: " + rupees);
int big = 300;
byte small = (byte) big;
System.out.println("300 as a byte: " + small);
long rounded = Math.round(price);
System.out.println("Rounded: " + rounded);
}
}Rupees: 99
300 as a byte: 44
Rounded: 100How it works
- Line 4 casts
99.99toint. A cast cuts off the decimal part; it does not round. The result is 99. - Line 8 squeezes 300 into a
byte, whose range is -128 to 127. Only the lowest 8 bits are kept: 300 − 256 = 44. The value is wrong, and Java gives no warning at runtime. - Line 11 uses
Math.round, which rounds to the nearest whole number instead: 100.
Try it yourself: cast -99.99 to int. Is the result -99 or -100?
char and int
A char is a number underneath, so it widens to int automatically, and an int can be cast to char:
public class Letters {
public static void main(String[] args) {
int code = 'A';
char next = (char) (code + 2);
System.out.println(code + " " + next);
}
}65 CConversion That Isn't Casting
Turning text into a number, or a number into text, isn't a cast; you call a method:
| From | To | Use |
|---|---|---|
"450" | int | Integer.parseInt("450") |
"99.5" | double | Double.parseDouble("99.5") |
450 | String | String.valueOf(450) or "" + 450 |
(int) "450" doesn't compile: casts only work between numeric types (and between related object types, which Level 2 covers).
Common Mistakes
Expecting a cast to round. (int) 9.99 is 9. Use Math.round to round.
Casting after dividing. (double) (7 / 2) is 3.0, because 7 / 2 is already 3. Cast first: (double) 7 / 2 is 3.5.
Using a cast to "fix" a compile error. If a long doesn't fit in an int, casting hides the bug. Change the variable's type instead.
Interview Corner
What is the difference between widening and narrowing conversion?
Widening converts a smaller numeric type to a larger one, such as int to long or double. Java does it automatically because no information is lost. Narrowing goes from larger to smaller, such as double to int; it needs an explicit cast because decimals can be cut off or the value can overflow.
What is the output of (int) 99.99 and (byte) 300?
(int) 99.99 is 99, because casting to int truncates the decimal part. (byte) 300 is 44, because only the lowest 8 bits are kept and 300 − 256 = 44.
Practice
- Easy: Write the result of each without running it:
(int) 7.9,(int) -7.9,(long) 2.5,(char) 66. - Harder: A price is
249.75. Print it as whole rupees by cutting off the paise, and again by rounding. Then print the paise part alone as anint(75).
Key Takeaways
Was this tutorial helpful?