It is a very basic question, but I don't seem to understand why this doesn't work. As far as I know, a and b would be pointers (in C thinking) to Integer objects. Why is the output 3 2 and not 3 3? I would have expected the value of b to also be incremented when incrementing a.
Integer a = new Integer(1);
Integer b = new Integer(2);
a = b;
a++;
System.out.print(a + " " + b);
Firstly, in case of java, the term used is an object 'reference' and not a 'pointer'. Basically it means that its a logical reference to the actual object.
Further more as already noted by Lagerbaer, its autoboxing-unboxing that is transparent which effectively increments the value, creates a new object and then assigns it back to the reference.
So at the end of the increment operation, there are two objects instead of one.
The increment operation after unboxing would probably look something like this :
a = Integer.valueOf(a.intValue()++);
The keyword here is auto-boxing
https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Basically, the java compiler automatically converts between the Integer class and the primitive type int in the "appropriate" context. One such context is assignment.
Integer is immutable, and a++, like a = a + 1, sets a to refer to a different immutable object.
In other words: a = b sets a to refer to the same object as b, but after a++, a and b refer to different objects again.
It is not equivalent to the C code that I suspect you're thinking of;
int *a = malloc(sizeof(*a));
*a = 1;
int *b = malloc(sizeof(*b));
*b = 2;
a = b;
(*a)++;
Thinking about Java references in terms of C pointers, or C++ references, easily leads the mind astray.
Integer is an immutable type, therefore you can't change the value within the method.
a = Integer.valueOf(a.intValue() + 1);
Before the a++ instruction you have:
+---------+
a --->| Integer |
b --->| 2 |
+---------+
Both a and b pointing at the same Integer object with value 2.
With the a++ instruction, Java autoboxing does these steps automatically for you:
Convert the Integer with value 2 to a primitive type int with value 2.
Increment the primitive value int to 3.
Convert the primitive type int with value 3 to an Integer with value 3, which will give you a new instance. As other pointed out, Integer is an immutable class, so you get different objects for different values.
So you end up with:
+---------+ +---------+
a --->| Integer | b --->| Integer |
| 2 | | 3 |
+---------+ +---------+
You are incrementing the value of a which will does not have any affect on the value of be as b is not related to a.
As Sean already answered, Integer (just like String) is immutable, that means it's value can't be changed. So your call to a++ actually created a new Integer with value a+1 and stored that as a. Meanwhile b is still pointing at the old Integer.
This can be shown by comparing the References (== operator). Before a++ a==b returns true (same reference/object). After a++ a==b returns false, as a is now pointing at a new Integer object.
Why do you think b should be 3? You never change that value!
Integer a = new Integer(1); // a is 1
Integer b = new Integer(2); // b is 2
a = b; // a now is 2
a++; // a now is 3
System.out.print(a + " " + b);
Related
What happens if you change the variable b, or what if you change a. What does the order have to do with anything.
I know count = count + 1 but the two variables is messing up my brain.
b = 7;
a = 7;
a = b;
a += 1;
What happens to b?
What happens to b?
Nothing happens to b.
When you do
a = b;
you're copying the value stored in b and putting it in a. (You're not making a an alias of b.)
When you then do a += 1; you're changing the value stored in a (and the value stored in b remains unchanged).
You can verify this by printing the final values after your code snippet:
System.out.println(a); // prints 8
System.out.println(b); // prints 7
What happens if you change the variable b, or what if you change a. What does the order have to do with anything.
a and b are two independent variables and changing one will never affect the other.
The order matters since when you do a = b the value of b is copied into a and whatever a stored before is discarded. If you had done a += 1 prior to a = b, then a would have been restored to 7 again.
int is raw type you don't copy reference but the value itself. This will work same way for Integer because it is immutable class.
int b = 7;
int a = 7;
a = b;
a+=1;
System.out.println(a);// ->8
System.out.println(b);// ->7
Still 7.
integer is raw type and if you assign a int variable to another int, just its value is received by the new one. Not the object itself.
b stays 7.
a becomes 8.
You could use System.out.println(); to print values of variables and find out yourself if you ever doubt.
That or use the debugger.
public static void main(String[] args) {
int b = 7; // b points to 7
int a = 7; // a points to 7
a = b; // b and a points to 7
a += 1; // a points to 8 now, b is still pointing to 7
System.out.println(a);
System.out.println(b);
}
output
8
7
When we do a += 1; we change the value stored in a (value stored in b is still same).
I understand that the values of the two would be the same (say 3 to 4). However, does the computer see the two as the same, and would they both be considered expressions?
Thanks in advance!
Yes to both, except that (value++) evaluates to the old value, whereas (value = value + 1) evaluates to the new value.
The direct equivalent of (value = value + 1) within an expression is (++value).
Note that neither of them are thread-safe.
For added fun, here are two more equivalent options:
value += 1;
value -= -1;
That's incorrect. Rather, ++value is the same as value=value+1.
++Value is a pre-increment. Value++ is a post-increment.
'Post' means after - that is, the increment is done after the variable is read. 'Pre' means before - so the variable value is incremented first, then used in the expression.
For example:
int i, x;
i = 2;
x = ++i;
// now i = 3, x = 3
i = 2;
x = i++;
// now i = 3, x = 2
No, my friend ++value is equivalent to value=value+1 as it is changing the new value preincrement operator
and value++ is changing the old value which is kept in the memory i.e. post incrementing it
This question already has answers here:
Weird Integer boxing in Java
(12 answers)
Why are autoboxed Integers and .getClass() values ==-equal, not only .equals()-equal?
(4 answers)
Closed 9 years ago.
I am comparing 2 pieces of code. First
Integer i=3;
Integer j=3;
if(i==j)
System.out.println("i==j"); //prints i==j
Second,
Integer i=3;
Integer j=new Integer(3);
if(i==j)
System.out.println("i==j"); // does not print
I have doubt that in the first snippet why i==j is being printed? Shouldn't the references be different?
It's to do with how boxing works. From the JLS section 5.1.7:
If the value p being boxed is true, false, a byte, or a char in the range \u0000 to \u007f, or an int or short number between -128 and 127 (inclusive), then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
Basically, a Java implementation must cache the boxed representations for suitably small values, and may cache more. The == operator is just comparing references, so it's specifically detecting whether the two variables refer to the same object. In the second code snippet they definitely won't, as new Integer(3) definitely isn't the same reference as any previously created one... it always creates a new object.
Due to the rules above, this code must always give the same result:
Integer x = 127;
Integer y = 127;
System.out.println(x == y); // Guarantee to print true
Whereas this could go either way:
Integer x = 128;
Integer y = 128;
System.out.println(x == y); // Might print true, might print false
Java pools integers between -128 and 127 and hence both the references are the same.
Integer i=3;
Integer j=3;
This results in autoboxing and 3 is converted to Integer 3. So for i is referring to an Integer object that is in constant pool, now when you do j=3, the same reference as that of i is assigned to j.
Whereas below code:
Integer j=new Integer(3);
always results in a new Integer creation, in heap. This is not pooled. And hence you see that both reference are referring to different objects. Which results in
Integer i=3;
Integer j=new Integer(3);
if(i==j)
System.out.println("i==j"); // **does not print**
Integer i=3;
Integer j=3;
if(i==j)System.out.println("i==j");
Here, 3 is being auto-boxed and hence i and j point to the same Integer.
Integer i=3;
Integer j=new Integer(3);
if(i==j)System.out.println("i==j"); // does not print
Here, i points to the auto-boxed Integer whereas j points to a new Integer and hence there references fail the equals == operator test.
But, here's some more food for thought.
Integer i=300;
Integer j=300;
if(i!=j)System.out.println("i!=j"); // prints i!=j
Why? Because, auto-boxing shares Integer instances between -128 to 127 only. This behaviour, however, may differ between different Java implementations.
I have doubt that in the first snippet why i==j is being printed?
Shouldn't the references be different?
Because,
Integer i=3;
Integer j=3;
are internally using Integer#valueOf() to perform autoBoxing . And oracle doc says about valueOf() method that:
Returns an Integer instance representing the specified int value. If a
new Integer instance is not required, this method should generally be
used in preference to the constructor Integer(int), as this method is
likely to yield significantly better space and time performance by
caching frequently requested values. This method will always cache
values in the range -128 to 127, inclusive, and may cache other values
outside of this range.
Since the value 3 is cached therefore, both variables i and j are referencing the same object. So, i==j is returning true. Integer#valueOf() uses flyweight pattern.
No they shouldn't, because java can use pre-fabricated Integer objects for small numbers when autoboxing.
Because in the second peice of code your first integer is being auto-boxed while the second is not.
This means a new Integer instance is being created on the fly. These 2 object instances are different. The equality check will return false there as the two instances are actually different pieces of memory.
Interpreter/JIT optimizer can put all 3's in same box. But if you force a "new" then you get another address.
Try
j=8; // after initialization of i and j
then see the j's address changed for first version.
In a similar fashion to strings, when autoboxing is used, such as in
Integer i = 3;
Integer j = 3;
Java can draw from a pool of prefabricated objects. In the case of j, there's already an Integer instance representing the value of 3 in the pool, so it draws from that. Thus, i and j point to the same thing, thus i == j.
In your second example, you're explicitly instantiating a new Integer object for j, so i and j point to different objects, thus i != j.
In Following Piece of Code:
Integer i=3;
Integer j=3;
if(i==j)
System.out.println("i==j");
Here, "==" compares reference with each other rather than the value.
So, Integer i and j both are referring to same reference in the memory.
while in Following Piece of Code:
Integer i=3;
Integer j=new Integer(3);
if(i==j)
System.out.println("i==j");
The reference to both values are changed because 'j' is newly created object/reference of Integer in memory while 'i' is just referring to a value.
Therefore, the output of 1st code is "i==j" and 2nd code does not have any output.
Hope this helps.
I was asked to write a swap without using temp variables or using xor and i came up with this.
In Java, this works, but in C/C++ this does not work.
I was under the impression that this would always work since the value of 'a' on the left side of the '|' would be stored in a register and then the assignment to 'a' would occur negating the effect on the assigned value for 'b'.
int a = 5;
int b = -13;
b = a | (0 & (a = b));
You are modifying a variable and reading its value without an intervening sequence point.
b = a + 0 * (a = b);
// reading a's value modifying a
This is undefined behavior. You have no right to any expectations on what the code will do.
The C/C++ compiler optimizes the expression 0 * (a = b) to simply 0 which turns your code fragment into:
int a = 5;
int b = -13;
b = a;
In C/C++, assigment are performed in the order of expression. In Java, assignments occur last regardless of other expressions.
e.g. This increments in C but does nothing in Java.
a = a++;
So I was asked this question today.
Integer a = 3;
Integer b = 2;
Integer c = 5;
Integer d = a + b;
System.out.println(c == d);
What will this program print out? It returns true. I answered it will always print out false because of how I understood auto (and auto un) boxing. I was under the impression that assigning Integer a = 3 will create a new Integer(3) so that an == will evaluate the reference rather then the primitive value.
Can anyone explain this?
Boxed values between -128 to 127 are cached. Boxing uses Integer.valueOf method, which uses the cache. Values outside the range are not cached and always created as a new instance. Since your values fall into the cached range, values are equal using == operator.
Quote from Java language specification:
If the value p being boxed is true,
false, a byte, a char in the range
\u0000 to \u007f, or an int or short
number between -128 and 127, then let
r1 and r2 be the results of any two
boxing conversions of p. It is always
the case that r1 == r2.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7
This is what is really happening:
Integer c = Integer.valueOf(5);
Integer d = Integer.valueOf(a.intValue() + b.intValue());
Java maintains a cache of Integer objects between -128 and 127. Compare with the following:
Integer a = 300;
Integer b = 200;
Integer c = 500;
Integer d = a + b;
System.out.println(c == d);
Which should print false.
It's because some of the (auto-boxed) Integers are cached, so you're actually comparing the same reference -- this post has more detailed examples and an explanation.
Caching happens outside of autoboxing too, consider this:
Integer a = 1;
Integer b = new Integer(1);
Integer c = Integer.valueOf(1);
System.out.println(a == b);
System.out.println(b == c);
System.out.println(c == a);
this will print:
false
false
true
Generally you want to stay away from == when comparing Objects