W3docs

Java Type Casting

Convert between primitive types in Java using implicit widening conversion and explicit narrowing casts, and avoid common pitfalls.

Type casting is converting a value from one type to another. In Java that comes in two flavours: widening conversions, which happen automatically and never lose information, and narrowing conversions, which require an explicit cast and can lose data.

Widening (implicit) conversion

A widening conversion moves a value into a larger type. The compiler does it for free — no syntax needed:

int i = 100;
long l = i;        // int → long (widening)
double d = l;      // long → double (widening)

System.out.println(i);   // 100
System.out.println(l);   // 100
System.out.println(d);   // 100.0

The standard widening order is:

byte → short → int → long → float → double
              char ↗

(char widens to int and onwards, but not to short or byte.)

Widening never loses range — a long always fits in a double's range, even if double cannot represent every long value exactly. Watch for that exact-representation gap at extreme values.

Narrowing (explicit) cast

A narrowing conversion moves a value into a smaller type. Java refuses to do this implicitly because data can be lost. You must spell it out with (targetType):

double d = 9.99;
int i = (int) d;   // explicit narrowing cast

System.out.println(i);   // 9 — the fractional part is dropped

The cast truncates toward zero — it does not round.

For integers, a cast keeps only the low-order bits:

int big = 130;
byte b = (byte) big;
System.out.println(b);   // -126 — overflow wraps around

byte is 8 bits, range -128…127. The bits of 130 (10000010) interpret as -126 in two's complement.

A common cast: integer division to a real number

Pure integer arithmetic uses integer division — 5 / 2 == 2, not 2.5. To get a real result, cast at least one operand before the division:

int total = 5;
int count = 2;

double avgWrong = total / count;          // 2.0 — division is still integer
double avgRight = (double) total / count; // 2.5 — total widened first

This is the single most common reason to reach for a cast.

Reference casts

The (Type) syntax also works on objects — though there it's a runtime check, not a conversion. Casting a reference is essentially saying "trust me, this object is of type X":

Object o = "Hello";
String s = (String) o;            // OK at runtime
System.out.println(s.length());   // 5

Object n = Integer.valueOf(7);
String bad = (String) n;          // throws ClassCastException at runtime

Pattern matching for instanceof (modern Java) lets you do the check and the cast in one step. Reference casts are covered properly in OOP and Polymorphism.

A working example

java— editable, runs on the server

When the compiler "helps" — and when it doesn't

A subtle case to watch for: arithmetic on byte, short, or char is automatically promoted to int before the operation. The result is an int:

byte a = 10;
byte b = 20;
// byte sum = a + b;       // compile error: result is int
byte sum = (byte) (a + b);  // explicit cast needed

This catches everyone the first time. Either store the result in int, or cast back.

Rules of thumb

  • Widen freely — no cast needed, no loss.
  • Narrow with a cast and a check — make sure the value really fits.
  • For real-number division of integers, cast one operand to double.
  • For monetary calculations, don't use double at all — use BigDecimal to avoid binary floating-point rounding errors.

What's next

Java Operators — the full overview of every operator the language ships with.

Practice

Practice

Which conversions require an explicit cast?