Take the 2-minute tour ×

Consider this code:

public class ShortDivision {
    public static void main(String[] args) {
        short i = 2;
        short j = 1;
        short k = i/j;

Compiling this produces the error

ShortDivision.java:5: possible loss of precision
found   : int
required: short
        short k = i/j;

because the type of the expression i/j is apparently int, and hence must be cast to short.

Why is the type of i/j not short?

share|improve this question
Because converting an int to a short would give possible loss of precision. (-32768 / -1) –  Mark Byers Feb 13 '10 at 9:06
add comment

3 Answers

up vote 11 down vote accepted

From the Java spec:

5.6.2 Binary Numeric Promotion

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value of a numeric type, the following rules apply, in order, using widening conversion (§5.1.2) to convert operands as necessary:




Otherwise, both operands are converted to type int.

For binary operations, small integer types are promoted to int and the result of the operation is int.

EDIT: Why is it like that? The short answer is that Java copied this behavior from C. A longer answer might have to do with the fact that all modern machines do at least 32-bit native computations, and it might actually be harder for some machines to do 8-bit and 16-bit operations.

See also: http://stackoverflow.com/questions/1214629/or-ing-bytes-in-c-gives-int/1214688#1214688

share|improve this answer
further: Binary numeric promotion is performed on the operands of certain operators: - The multiplicative operators *, / and % –  akf Feb 13 '10 at 7:54
OK, I understand that the language specification says that the language should behave like this (otherwise the compiler wouldn't generate the error in the first place). But I don't understand the motivation behind it. Why are they promoting the types before doing the division rather than just dividing the shorts? –  flodin Feb 13 '10 at 8:01
My bet is on "thats the way it is in C". Java was designed to be attractive to C++ programmers - that requires things to be the same –  Thorbjørn Ravn Andersen Feb 13 '10 at 8:58
Thanks for the link, that seemed like a reasonable enough explanation. –  flodin Feb 13 '10 at 9:27
add comment

Regarding the motivation: lets imagine the alternatives to this behaviour and see why they don't work:

Alternative 1: the result should always be the same as the inputs.

What should the result be for adding an int and a short?

What should the result be for multiplying two shorts? The result in general will fit into an int, but because we truncate to short, most multiplications will fail silently. Casting to an int afterwards won't help.

Alternative 2: the result should always be the smallest type that can represent all possible outputs.

If the return type were a short, the answer would not always be representable as a short.

A short can hold values -32,768 to 32,767. Then this result will cause overflow:

short result = -32768 / -1; // 32768: not a short

So your question becomes: why does adding two ints not return a long? What should multiplication of two ints be? A long? A BigNumber to cover the case of squaring integer min value?

Alternative 3: Choose the thing most people probably want most of the time

So the result should be:

  • int for multiplying two shorts, or any int operations.
  • short if adding or subtracting shorts, dividing a short by any integer type, multiplying two bytes, ...
  • byte if bitshifting a byte to the right, int if bitshifting to the left.
  • etc...

Remembering all the special cases would be difficult if there is no fundamental logic to them. It's simpler to just say: the result of integer operations is always an int.

share|improve this answer
What people want, isn't always the same as what is a good idea if you designed it again. A good example is the QWERTY keyboard arrangement. Originally designed to slow down typists so that typewriters wouldn't jam up. Still, I can't imagine using anything else as I'm used to it. –  Peter Lawrey Feb 13 '10 at 8:50
@Peter Lawrey: Yep. If Henry Ford had asked people what sort of car he should manufacture, many would have been asking for a cart with 6 horses instead of 4. Listening to what your users want is a good thing, but sometimes you need to give them something different from what they want because they're not even able to imagine a different solution than what they're used to. –  Mark Byers Feb 13 '10 at 9:18
For languages without operator overloading, why not have the result be the smaller of (largest possible result) or (size of receiving container)? In most cases, such a rule would yield code which was as small or smaller than anything which could be expressed that would yield arithmetically-correct results using approach #1. For example, if variables are 32 bits, p=(x*y)/z; would do a 32x32->64 multiply and a 64/32->32 divide. If p and z were 16 bits, it would do a 32x32->64 multiply, a 64->32 overflow-checked reduction, and a 32/16->16 divide. –  supercat Feb 10 at 22:14
add comment

It just a design choice to be consistent with C/C++ which were dominate languages when Java was designed.

For example, i * j could be implemented so the type is promoted from byte => short, short => int, and int => long, and this would avoid overflows but it doesn't. (It does in some languages) Casting could be used if the current behaviour was desired, but the loss of some bits would be clear.

Similarly i / j could be prompted from byte/short => float or int/long => double.

share|improve this answer
add comment

Your Answer


