Back to Primitive Types & Wrappers
Q10Question 10 of 11

What is the difference between widening and narrowing conversions?

Key Concepts
  • Widening: smaller type to larger type (byte→int→long→double) – implicit, no cast needed
  • Narrowing: larger type to smaller type (double→int→byte) – explicit cast required, may lose data
  • Narrowing truncates: (int) 3.99 gives 3, not 4 – it drops the fraction, does not round
  • Narrowing overflows: (byte) 300 gives 44 – keeps only the low 8 bits
  • char widens to int implicitly, but int→char and byte→char require explicit casts
  • Widening long→float can lose precision even though it preserves magnitude

Definition

Widening goes from a smaller type to a larger type and is automatic. Narrowing goes from a larger type to a smaller type, requires a cast, and can lose data through truncation or overflow.

Two types of primitive conversion:

DIAGRAM
- **Widening (implicit).** Moving a value to a type with a larger range. `byte → short → int → long → float → double`, and `char → int`. No cast needed. Generally safe, though `long → float` can lose precision.
- **Narrowing (explicit).** Moving a value to a type with a smaller range. Requires a `(type)` cast. Can lose data: `(int) 3.99` truncates to 3, and `(byte) 300` overflows to 44.

Widening is moving money from a small drawer to a bigger safe – everything fits, nothing is lost. Narrowing is pouring the big safe's contents back into the small drawer – you must agree to spill whatever does not fit, and the spillage is lost data.

Understanding the Concepts

What is widening?

Widening moves a value from a smaller-range type to a larger-range type. The compiler does it automatically.

JAVA
byte b = 42;
short s = b;       // byte → short (implicit)
int i = s;         // short → int (implicit)
long l = i;        // int → long (implicit)
float f = l;       // long → float (implicit, but may lose precision!)
double d = f;      // float → double (implicit)

char c = 'A';      // 65
int code = c;      // char → int: 65 (implicit)

The full widening chain: byte → short → int → long → float → double, and char → int.

What is narrowing?

Narrowing moves a value from a larger-range type to a smaller-range type. It always requires an explicit cast.

JAVA
// Truncation: decimal part dropped (NOT rounded)
double price = 1234.99;
int rupees = (int) price;     // 1234 (paise lost!)

// Overflow: only low bits kept
int big = 300;
byte small = (byte) big;      // 44 (300 mod 256, reinterpreted as signed)

// long to int: high 32 bits dropped
long huge = 3_000_000_000L;
int truncated = (int) huge;   // -1294967296 (overflow)

Where does char fit in the conversion chain?

char is special because it is unsigned (0 to 65535) while byte and short are signed.

JAVA
// char → int: widening (implicit, safe)
char c = '₹';   // 8377
int code = c;    // 8377 (no cast needed)

// int → char: narrowing (explicit cast required)
int value = 66;
char letter = (char) value;  // 'B'

// byte → char: narrowing (both are 16 bits, but byte is signed)
byte b = 65;
// char c = b;    // COMPILE ERROR: byte → char is narrowing
char c2 = (char) b;  // 'A' (cast required)

Does widening ever lose data?

Yes. Widening from long to float can lose precision because float has only 24 bits of mantissa.

JAVA
long exact = 123_456_789_012_345L;
float approx = exact;              // widening, no cast needed
System.out.println(approx);        // 1.23456788E14 (last digits lost!)
System.out.println((long) approx); // 123456788103168 (different!)

The value fits in float's range but not in its precision. This is a silent loss that produces wrong numbers in banking calculations.

What about compile-time constants?

The compiler allows narrowing without a cast when the right side is a compile-time constant that fits:

JAVA
byte b = 100;        // OK: 100 is a constant that fits in byte
byte c = 127 + 1;    // COMPILE ERROR: 128 does not fit in byte

final int x = 10;
byte d = x;          // OK: x is a final constant, 10 fits

int y = 10;
// byte e = y;       // COMPILE ERROR: y is not a constant

What are common mistakes?

DIAGRAM
- **Casting double to int for money.** `(int) 1234.99` gives 1234, not 1235. Use `BigDecimal` for money.
- **Assuming long→float is lossless.** It is widening (no cast) but can silently lose precision.
- **Forgetting byte→char needs a cast.** Even though both are 16-bit-ish, byte is signed and char is unsigned.
- **Casting without checking range.** `(byte) 300` gives 44, not 300. Validate the range before casting.

What should a senior engineer know?

  • Math.toIntExact(long) throws ArithmeticException if the long does not fit in an int. Use this instead of a raw cast.
  • BigDecimal.intValueExact() throws if the decimal has a fractional part. Use for safe money-to-int conversion.
  • Widening in method calls. Passing a byte to a method expecting int is a widening conversion and happens automatically. No cast needed.
  • Narrowing in switch. A switch on a byte variable can use int case constants, but only if they fit in byte range.

Visual Overview

DIAGRAM
  Widening chain (implicit, no cast):
    byte → short → int → long → float → double
                    ↑
                   char

  Narrowing (explicit cast, may lose data):
    double → float → long → int → short → byte
    (truncation)             (overflow)

  char special rules:
    char → int     implicit (widening)
    int → char     explicit cast (narrowing)
    byte → char    explicit cast (signed → unsigned)

  Precision loss in widening:
    long 123456789012345 → float → 1.23456788E14 (digits lost)

Key Takeaway

Widening moves a value to a larger type and is automatic. Narrowing moves to a smaller type, requires a cast, and can lose data. Narrowing truncates doubles (drops the fraction) and overflows integers (keeps only the low bits). char widens to int implicitly but needs an explicit cast from int or byte because of the signed/unsigned difference. And widening from long to float can silently lose precision even though the compiler allows it without a cast.

One sentence to remember: widening is automatic and safe in magnitude, narrowing requires a cast and can truncate or overflow, and long-to-float widening is the sneaky case that loses precision silently.

---

Share
Use ← → arrow keys to navigate