4

In Java, the following code does not compile:

int val = 1;
short shortVal = val;  // Incompatible types

Anyone know why Java chooses to complain about this assignment, instead of simply truncating, when an integer × integer is also likely to overflow?

To illustrate:

int val = 46340;
int result = val * val;                    // 2147395600
System.out.println(result);
int overflowVal = 46341;
int result2 = overflowVal * overflowVal;   // -2147479015
System.out.println("Quietly overflowed: " + result2);
1
  • 1
    Because complaining in the first case doesn't cause infinite amounts of frustration? Dec 20, 2011 at 19:18

5 Answers 5

12

In the first case, the compiler knows that you're facing a potential loss of precision, so it can stop you. In the second case the overflow happens during a runtime calculation - though your example trivialy causes an overflow, there is no way for the compiler to check such occurrences in general case so it doesn't.

2
  • 1
    It's still only a potential loss... in either case. Yes, it can't stop you in the second case, but that's not a real reason why it should, in the first.
    – Nicole
    Dec 20, 2011 at 21:02
  • 2
    @Renesis, rockets have literally blown up in the sky due to simple precision problems like in your first example. The compiler has it right. Use a typecast if you want it to act differently.
    – riwalk
    Dec 21, 2011 at 14:16
1

Int to Short is a type conversion, and java requires explicit casts even where the type conversion could be deduced automatically.

Java's lax treatment of incorrect results from integer arithmetic is a separate matter. It's a very good question why integer overflow doesn't cause a runtime exception.

1
  • 1
    Could be a concession to speed but more likely it's just because that's the way C did it, they tried to follow patterns from C wherever it made sense.
    – Bill K
    Dec 20, 2011 at 20:46
1

Type mismatch in a calculation is not really an issue, since the result of the calculation is still definable even for operands of different bit sizes. The issue of arithmetic overflow at runtime is more general, as it can happen even in calculations among same bit size operands, and there clearly is no point to have the compiler warn us about the possibility that we may have an overflow every time we increment an integer. So, the question boils down to why does java not offer something like the 'checked' keyword of C# so as to offer the possibility of catching arithmetic overflow at runtime. But that would be the subject of a different question.

0

The int to short assignment is a type error in the "computer sciency" definition of the term. The intent is to prevent programmers from accidentally doing something bad (like assigning something into a short that can't be represented in a short). Multiplying an int and a short is also technically a type error in the "computer sciency" definition of the term, but there is less of a chance for mischief here since the type system gets to decide what type to make the result of an int x short operation. Most people wouldn't like to cast their shorts to ints every time math is done with a short and and int, so compilers will do this for you.

In a nutshell: With assignment, the types are constrained, there's no room to budge. With arithmetic, the type system gets to decide what the resulting type should be, and chooses a compatible type in this case (int) and inserts any required casts for you.

0

It'd be weird if int * int = long. Internally, that's exactly what (x86) processors do anyways, but it would make for some rather interesting programming challenges. Occasional overflow is easier to handle than auto-recasting everytime you do an operation!

So, in short, int to short is prevented because it's easy to prevent. Int/int overflow is allowed rather than upcasting because upcasting would bring about even more ugliness. Looks like a design decision based on the lesser of multiple evils.

1
  • If I were designing a language, I would specify that operations on normal integral numeric types would generally be performed as if they were performed on the largest signed integral type, with the caveat that explicit disambiguating typecasts may be needed in some contexts involving function overloading. The compile-time analysis would not be hard; some code might generate slightly less efficient code than expected, but unexpected overflows are bad and should be trapped. Programmers wanting "wrapping" behavior should use wrapping integer types.
    – supercat
    Jan 17, 2014 at 0:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.