Back to Primitive Types & Wrappers
Q11Question 11 of 11

What is implicit coercion in mixed expressions?

Key Concepts
  • In a mixed expression, Java promotes both operands to a common type before computing
  • Promotion hierarchy: double > float > long > int – byte/short/char always promoted to int
  • 'A' + 1 = int 66 (char promoted to int), cast back to char for 'B'
  • long + float = float (float outranks long in the hierarchy, but precision can be lost)
  • 5 / 2 = 2 (integer division) but 5 / 2.0 = 2.5 (one operand is double, promotes the other)
  • Compound += hides a narrowing cast: char c = 'A'; c += 1; gives 'B' without explicit cast

Definition

In a mixed expression, Java promotes both operands to a common type (at least int) before computing. This is called binary numeric promotion.

Binary numeric promotion follows a fixed cascade:

  • Either is double? Both become double.
  • Either is float? Both become float.
  • Either is long? Both become long.
  • Otherwise? Both become int. This means byte, short, and char are always promoted to int.

The result type is always the promoted type. There is no arithmetic that returns byte, short, or char.

Two bank tellers must do a calculation together but work in different denominations. Before adding, they convert to a single agreed denomination so the math is consistent. Small denominations (byte, short, char) always convert to the standard int denomination. If one teller works in a larger denomination (long, float, double), the other converts up to match.

Understanding the Concepts

Why does 'A' + 1 give 66?

The character 'A' has the numeric value 65. When you add an int to a char, the char is promoted to int first.

JAVA
char a = 'A';          // 65
int result = a + 1;    // 65 + 1 = 66 (int, NOT char)
System.out.println(result);  // 66

char b = (char)(a + 1);  // cast int 66 back to char
System.out.println(b);    // B

Without the cast, you cannot assign an int result to a char variable because that is a narrowing conversion.

Why does the constant expression 'A' + 1 assign to char without a cast?

JAVA
char b = 'A' + 1;  // compiles! 66 is a constant that fits in char

This is a special rule: if the entire right side is a compile-time constant and the result fits in the target type, the compiler allows it. But if either operand is a variable, the rule does not apply:

JAVA
int one = 1;
// char b = 'A' + one;  // COMPILE ERROR: not a constant expression
char b = (char)('A' + one);  // explicit cast needed

Why does long + float give float?

The promotion hierarchy puts float above long. This is surprising because long has 64 bits of integer precision while float has only 24 bits of mantissa.

JAVA
long bigLong = 123_456_789_012_345L;
float f = 1.0f;
float result = bigLong + f;  // long promoted to float first!
System.out.println(result);  // 1.23456788E14 (precision lost!)

The long is converted to float before the addition. The conversion rounds the long's value to fit in float's 24-bit mantissa, losing the last digits. In banking, this is why you never mix long amounts with float arithmetic.

Why does 5 / 2 give 2 but 5 / 2.0 give 2.5?

JAVA
System.out.println(5 / 2);    // 2 (integer division, fraction dropped)
System.out.println(5 / 2.0);  // 2.5 (int 5 promoted to double, then divided)
System.out.println(5.0 / 2);  // 2.5 (same: promotion to double)

When both operands are int, the division is integer division and the remainder is dropped. When either operand is a floating-point type, the other is promoted and the division is floating-point.

In banking, this matters for interest calculations:

JAVA
// WRONG: integer division gives 0
int rate = 7;
int months = 12;
int monthlyRate = rate / months;  // 0 (not 0.583)

// CORRECT: force floating-point division
double monthlyRate = rate / 12.0;  // 0.5833...

// BEST for money: use BigDecimal
BigDecimal monthlyRate = new BigDecimal("7").divide(new BigDecimal("12"), 6, RoundingMode.HALF_UP);

How does += hide a narrowing cast?

JAVA
char c = 'A';
// c = c + 1;     // COMPILE ERROR: c + 1 is int, cannot assign to char
c += 1;           // compiles! equivalent to c = (char)(c + 1)
System.out.println(c);  // B

byte b = 127;
b += 1;           // compiles! equivalent to b = (byte)(b + 1)
System.out.println(b);  // -128 (silent overflow!)

Compound operators (+=, -=, *=, etc.) insert an implicit narrowing cast to the left-hand type. This is convenient but can silently overflow.

What about String + int?

The + operator with a String converts the other operand to a String via String.valueOf(). This is string concatenation, not numeric promotion.

JAVA
System.out.println("Balance: " + 1000);      // "Balance: 1000"
System.out.println("Sum: " + 1 + 2);         // "Sum: 12" (left to right: string + int + int)
System.out.println("Sum: " + (1 + 2));       // "Sum: 3" (parentheses force numeric first)
System.out.println(1 + 2 + " rupees");       // "3 rupees" (1+2 is numeric, then concat)

What are common mistakes?

  • Assuming byte + byte returns byte. It returns int. Cast needed to store back.
  • Integer division when you wanted a fraction. 7 / 12 is 0. Use 7.0 / 12 or BigDecimal.
  • Relying on += without understanding the hidden cast. byte b = 127; b += 1; wraps to -128.
  • Mixing long with float. Long precision is lost. Use double or BigDecimal instead.
  • String + int confusion. "1" + 2 + 3 is "123", not "6". Parenthesize the numeric part.

What should a senior engineer know?

  • There are no byte, short, or char arithmetic bytecodes. The JVM uses iadd (int add) even for byte operands. Promotion to int matches the hardware reality.
  • Promotion applies to comparisons too. Comparing a char to an int compares their numeric values. 'A' == 65 is true.
  • Ternary result type follows promotion rules. condition ? byteVal : intVal promotes the byte to int.
  • Bitwise operators also promote. ~(byte)0xFF is an int, not a byte.

Visual Overview

DIAGRAM
  Binary Numeric Promotion:
    either double?  → both double
    either float?   → both float
    either long?    → both long
    otherwise       → both int (byte/short/char promoted)

  Examples:
    'A' + 1       → int 65 + int 1 = int 66
    long + float  → float + float = float (precision loss!)
    5 / 2         → int / int = int 2 (truncated)
    5 / 2.0       → double / double = double 2.5
    byte + byte   → int + int = int

  String special:
    "x" + 1 + 2   → "x12" (string concat left to right)
    1 + 2 + "x"   → "3x"  (int add first, then concat)

Key Takeaway

When the two sides of an arithmetic operator have different types, Java promotes both to a common type before computing. The minimum is always int, so byte, short, and char arithmetic always produces an int result. If either side is long, float, or double, the other is promoted to match.

This explains why 'A' + 1 gives the int 66 instead of the char 'B'. The char is promoted to int, the addition happens in int, and the result is int. To get a char back, you need an explicit cast. The compound operator c += 1 compiles without a cast because it inserts the narrowing cast automatically.

The long + float case is the trap: float outranks long in the hierarchy, so the long is converted to float first, and large longs lose precision because float has only 24 bits of mantissa. And integer division (5 / 2 = 2) versus floating-point division (5 / 2.0 = 2.5) depends entirely on whether one operand is a floating type.

One sentence to remember: Java promotes both operands to at least int and up to the widest type, so char and byte arithmetic is always int arithmetic, and long plus float is float with possible precision loss.

---

Share
Use ← → arrow keys to navigate