Why would i+=l compile, where i is int and l is long?
Asked Answered
V

3

8

I spotted Java's +=, -=, *=, /= compound assignment operators (good question :)), but it had a part that I don't quite understand. Borrowing from that question:

int i = 5;
long l = 8;

Then i = i + l; will not compile but i += l; will compile fine.

The accepted answer to the linked question states that:

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.

which gives that i += l; is the same as i = (int)((i) + (l)); with the exception that i is only evaluated once.

A long may be (IIRC even is guaranteed to be) longer than an int, and thus can hold a much greater range of values.

Given that this situation can very easily cause data loss due to necessary narrowing conversion at some point during execution of the statement (either r-value expression evaluation, or assignment), why is i += l; not a compile-time error or at least warning?

Vermicelli answered 3/1, 2012 at 14:3 Comment(12)
That question is exactly the same and answers it too. (i.e. it is because i += l; does a cast, it's the same as i = (int)(i + l); , if the type of i is int.Yarak
What exactly did you not understand about the answer to the question you're linking to? It's asking nearly exactly the same, and the information you need should all be in there - if you still have trouble understanding it, you'll have to be more specific!Phia
@Yarak is right. You aren't asking about part of the question, you're duplicating it exactly. If you've read that question and the answers, perhaps you could instead explain what you don't get about the (highly voted) answer given.Hegel
possible duplicate of Java += operatorHegel
@nos, I guess the point of the OP is that this implicit narrowing conversion may result in data loss, and the compiler could (should) at least warn about this.Raddatz
Though is is clearly a duplicate, downvoting seems a bit rash, here.Tobacco
@Raveline: Why is downvoting a duplicate bad, particularly when the OP knew about the duplicate and it was from just a few hours ago? If the goal of downvoting questions is to reduce noise and make sure that questions worth answering are the most visible, isn't downvoting the appropriate response? The OP shouldn't take it personally.Hegel
@PéterTörök is correct in his interpretation of the question. Edited to clarify.Vermicelli
I must admit that it's a little curious that this question received so much attention initially, yet nothing since my (hopefully clarifying) edit...Vermicelli
What does E1 is evaluated only once mean? What's the difference between i += 5 and i = i + 5? In Java Concurrency in Practice it is said that even i++; is not an atomic operation.Spectator
@AmirPashazadeh, that's not a comment to my question.Vermicelli
@MichaelKjörling I know, but I was confused.Spectator
L
8

Given that this situation can very easily cause data loss due to necessary narrowing conversion at some point during execution of the statement (either r-value expression evaluation, or assignment), why is i += l; not a compile-time error or at least warning?

It probably should be, as you said, either a compile-time error or at least warning. Most books and tutorials that I'm aware of introduce x += y; as shorthand for x = x + y;. I honestly don't know of any that make the distinction called out in section 15.26.2 Compound Assignment Operators of the JLS except one.

In chapter 2 (puzzle 9) of Java Puzzlers: Traps, Pitfalls, and Corner Cases the authors (Joshua Bloch & Neal Gafter) ask you to provide declarations for x and i such that this is a legal statement:

x += i;

and this is not:

x = x + i;

There are lots of solutions, including the first two lines of code that you posted in your question. The authors warn against using compound assignment operators on variables of types byte, short, and char, and recommend that when using these operators on variables of type int you should make sure that the RHS expression is not a long, float, or double.

They conclude with the following observation (emphasis mine):

In summary, compound assignment operators silently generate a cast. If the type of the result of the computation is wider than that of the variable, the generated cast is a dangerous narrowing cast. Such casts can silently discard precision or magnitude. For language designers, it is probably a mistake for compound assignment operators to generate invisible casts; compound assignments where the variable has a narrower type than the result of the computation should probably be illegal.

Lawton answered 16/2, 2012 at 0:17 Comment(0)
C
14

Basically, because i += l is compiled as if it were written i = (int) (i + l). There are similar "surprises" when adding int values to byte and char variables -- the assignment operator works while the plain addition operator does not.

Covin answered 3/1, 2012 at 14:6 Comment(3)
This is already explained in the accepted answer to the question referred above. I guess the point of the OP is that this implicit narrowing conversion may result in data loss, and the compiler could (should) at least warn about this.Raddatz
Would be even better to quote the Java specs : java.sun.com/docs/books/jls/third_edition/html/…Tobacco
So, unless I'm missing something, which part of Otherwise, the saved value of the left-hand variable and the value of the right-hand operand are used to perform the binary operation indicated by the compound assignment operator. says implicit downcasting should be done with no indication that such is done? Or is that somewhere else? If the latter, I don't see the answers to the other question necessarily being applicable.Vermicelli
L
8

Given that this situation can very easily cause data loss due to necessary narrowing conversion at some point during execution of the statement (either r-value expression evaluation, or assignment), why is i += l; not a compile-time error or at least warning?

It probably should be, as you said, either a compile-time error or at least warning. Most books and tutorials that I'm aware of introduce x += y; as shorthand for x = x + y;. I honestly don't know of any that make the distinction called out in section 15.26.2 Compound Assignment Operators of the JLS except one.

In chapter 2 (puzzle 9) of Java Puzzlers: Traps, Pitfalls, and Corner Cases the authors (Joshua Bloch & Neal Gafter) ask you to provide declarations for x and i such that this is a legal statement:

x += i;

and this is not:

x = x + i;

There are lots of solutions, including the first two lines of code that you posted in your question. The authors warn against using compound assignment operators on variables of types byte, short, and char, and recommend that when using these operators on variables of type int you should make sure that the RHS expression is not a long, float, or double.

They conclude with the following observation (emphasis mine):

In summary, compound assignment operators silently generate a cast. If the type of the result of the computation is wider than that of the variable, the generated cast is a dangerous narrowing cast. Such casts can silently discard precision or magnitude. For language designers, it is probably a mistake for compound assignment operators to generate invisible casts; compound assignments where the variable has a narrower type than the result of the computation should probably be illegal.

Lawton answered 16/2, 2012 at 0:17 Comment(0)
G
1

the reason for this is so you can do:

byte b = 1;

b += 1;

if += was expanded to b = b + 1 then the expression would not type check because the expression "b + 1" is of type int. all integral expressions in java are at least the int type even if you add two bytes together.

public class Test {
  public static void main(String[] args) {
    byte b = 1;
    byte c = 2;
    byte d = b + c;
  }
}


Test.java:5: possible loss of precision
found   : int
required: byte
    byte d = b + c;
               ^
1 error
Gentleness answered 16/2, 2012 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.