Type Casting
Converting between Java's numeric types safely, and where implicit conversion stops and explicit casting begins.
2 min read
Because Java is statically typed, moving a value from one type to another isn't always automatic. Some conversions happen for free; others require you to say explicitly that you accept the risk.
Widening (implicit) conversion
Converting a smaller type to a larger, more precise one is safe — no information can be lost — so Java does it automatically. This is called widening.
int wholeNumber = 42;
double asDouble = wholeNumber; // widening: int -> double, no cast needed
long bigNumber = wholeNumber; // int -> long, also automaticThe general widening order is byte -> short -> int -> long -> float -> double (with char also convertible to int and beyond). Each step to the right can represent everything the type on the left could, plus more.
Narrowing (explicit) casting
Going the other direction — a larger type into a smaller one — risks losing data, so Java forces you to acknowledge that explicitly with a cast: (type)value.
double price = 19.99;
int wholeDollars = (int) price; // 19 -- the decimal part is simply dropped, not rounded
long bigValue = 3_000_000_000L;
int truncated = (int) bigValue; // overflows silently -- produces a nonsensical valueTwo things to watch for here. First, casting a double to an int truncates rather than rounds — (int) 19.99 is 19, not 20. If you want rounding, use Math.round() first. Second, narrowing an out-of-range value doesn't throw an error — it silently wraps around to a meaningless number. The compiler requires the cast as a safety acknowledgment, but it can't stop you from casting a value that genuinely doesn't fit.
Casting between numbers and char
char is really a 16-bit numeric type under the hood (representing a Unicode code point), so it participates in casting too:
char letter = 'A';
int code = letter; // widening: char -> int, gives 65
int nextCode = code + 1;
char nextLetter = (char) nextCode; // narrowing back to char: 'B'Casting object references
Casting isn't only for numbers — it also applies to object references, particularly when working with inheritance (covered later in this course). Casting a reference doesn't convert the object itself; it changes how you're allowed to treat it, and an invalid cast between unrelated types throws a ClassCastException at runtime rather than failing to compile, since the compiler can't always know the object's real type in advance.
Object value = "hello";
String text = (String) value; // valid: value really is a String underneathThe rule of thumb: widen freely, narrow deliberately, and always double-check that a narrowing cast won't silently corrupt a value you actually care about.
Test what you just learned
4 quick questions. Get all of them right to unlock the next lesson.
You can take the quiz without an account — logging in just lets your result count toward your progress.