1

This Java code

public class test{
   public static void main(String[] args){
      byte[] a = new byte[1];
      a[0] = 1;
      byte x = 1;
      x = x + a[0];
      System.out.println(x);
  }
}

throws the following compile error:

test.java:10: possible loss of precision
found   : int
required: byte
    byte y = x + a[0];
               ^
1 error

huh? What is going on here? all variables are declared as byte. Explicitly casting the 1's to byte doesn't make any difference. However, change to

public class test{
   public static void main(String[] args){
      byte[] a = new byte[1];
      a[0] = 1;
      byte x = 1;
      x += a[0];
      System.out.println(x);
  }
}

and everything compiles fine. I'm compiling with java version 1.6.0_16, build-b01. My questions are: Is this a bug or a feature? Why does += perform differently than + ?

3 Answers3

3

You will find this answer of great help.

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

Notice the explicit cast that is introduced when using the compound assignment operator.

Community
  • 1
  • 1
Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
2

In the first case the result is int. so you need to cast it explicitly for byte. But in the second case, java will convert the value automatically to byte. So casting is not needed and no exception.

MGPJ
  • 1,062
  • 1
  • 8
  • 15
2

This is the result of a quirk in the Java Language Specification. The default type of an integral expression (such as x + a[0]) is int, and the compiler then complains when you try to assign the result to a byte without a cast. Technically speaking, of course, it's correct, and you could easily overflow the byte precision. Using the += syntax avoids the separate x + a[0] expression and its implicit widening conversion:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • That addition of two integral types smaller than `int` is promoted to `int` is defined in [5.6.2 Binary Numeric Promotion](http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2), not in the 15.1.8.2 – Mark Rotteveel Sep 25 '13 at 14:30
  • @MarkRotteveel I quoted 15.18.2 for the direction that numeric promotion is performed, which is what makes the expression of type `int`. 5.6.2 defines exactly how that happens (sign extension, in this case). – chrylis -cautiouslyoptimistic- Sep 25 '13 at 14:31
  • It isn't sign-extension, but the widening primitive conversion (point 2, last bullet) that is applied for both operands (_"Otherwise, both operands are converted to type int."_) – Mark Rotteveel Sep 25 '13 at 14:33
  • @MarkRotteveel "A widening conversion of a signed integer value to an integral type T simply sign-extends the two's-complement representation of the integer value to fill the wider format." (5.1.2) This back-and-forth is basically pointer-chasing. – chrylis -cautiouslyoptimistic- Sep 25 '13 at 14:35
  • It is 5.6.2 that **defines** that `byte + byte` is promoted to `int + int` – Mark Rotteveel Sep 25 '13 at 14:39