Do wrapper class objects get unboxed while being assigned to another object? - java

When we assign objects of the same type to one another, the new object stores the address of the object that's being assigned to it. For instance, if I have my own class named CLA then the following code will produce 11 as the output:
public class CLA{
int val;
public static void main(String...args){
CLA ob1 = new CLA();
ob1.val = 10;
CLA ob2 = ob1;
ob1.val++;
System.out.printf("%d", ob2.val);
}
}
because ob2 would refer to ob1 and consequently show ob1's val.
However, the same doesn't happen for Wrapper classes. When I assign an Integer object to another, the operation simply behaves like we're dealing with values and not objects. As opposed to the above code, the output of the below code is 10:
Integer x = 10; //auto-boxed as new Integer(10)
Integer y = x;
x++;
System.out.printf("%d", y.intValue());
Why does this happen?
Do wrapper class objects get unboxed while being assigned to another object, so as to pass the value instead of the address??

When you do x++, it is the same as x = x + 1 so it is actually a new instance of Integer assigned to x but y still points to the old instance which value is 10.
Keep in mind that wrapper instances are immutable.

For an Integer x, the expression x++ can be understood like x = new Integer(x.intValue() + 1);. Its not exactly the same, but helps for understanding.
So, it doesn't modify the Integer object with the value 10 that x pointed to before the x++, it creates a new Integer object with the value 11 independent of the original 10 Integer, and assigns this 11 Integer to x.
But there's nothing in the x++ expression that would make y point to a different Integer instance. So y still points to the original 10.
That's the difference to the CLA example where you don't introduce a new instance with ob1.val++, but modify the single instance. If the Integer class had a public field value, then x.value++ would show the behaviour you expected - but the value field is (for good reason) private - not accessible to the outside.

Related

Java Object reference and garbage collection

I'm currently studying towards my Java associate certificate and I have the official textbook for study. In the text book is the following example code.
public class Island {
Island i;
public static void main(String[] args) {
Island i2 = new Island();
Island i3 = new Island();
Island i4 = new Island();
i2.i = i3;
i3.i = i4;
i4.i = i2;
I understand here that I have initialised 3 Island objects with reference variables i2, i3 and i4 which each point to their own object. i2 is then redirected to point towards i3 and i3 towards i4 etc. What I don't understand is the need for the "i2.i" dot operator, what exactly is it doing here ? is i2 = i3 not as equally valid ?
If anyone has any good resources on where I can read quite in depth into all of the applications of the dot operator in java that would also be helpful, thanks.
You're using an instance variable of the same type as the class itself (see line Island i). This means, that the class Island holds an attribute i of the same type Island. Every island has therefore a link to another island. Your assignment of i2.i = i3; defines the instance variable of i2 to be i3. In other words: i2 has a link to i3. You can get i3 if you have i2.
If you used the assignment i2 = i3, the value of i2 would be overridden by the reference of i3. This means that i2 is not used anymore and the object behind i3 would also be the same object behind i2 (same object, 2 different variable names).
It's important to be careful with the details here.
You have indeed created three objects, but the objects are distinct from the variables.
Let's simplfy: Consider Island x = new Island();, and Island y; You have two variables, x and y, but only one object. The object doesn't have a name, but it is bound to the variable x, so when you say x, you get that object. And when you say y, you get nothing (y is null).
The dot accesses the object denoted by by the expression that precedes it. So x.i accesses the i member variable of the object that is bound to x, and similarly, y.i is attempting to access a member-variable of no object at all, which causes an exception to be thrown.
So now it is clear that you can say x.i = x; to set the member variable Island.i of the object bound to x to the value that happens to be the same object. Or you could set it to something else, like x.i = new Island(); or x.i = y;.
The dot doesn't have to be preceded by a variable, any expression will do. For example, you could say (new Island()).i = x; to create a new object (which again doesn't have a name; objects never have names) and bind the i member of that object to the object bound to x. Since this object is never bound to any variable, it is immediately eligible for collection.
The point of your code example is that all objects are bound to variables that exist beyond the scope of the i1, i2 and i3 (namely to the member variables of the three objects), and thus they form a reference cycle. An interesting question on the topic of garbage collection is whether the three objects are eligible for collection.

Why does the value of x not change, and how would you change it? -Understanding Methods [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
static void number(int x){
x=42;
}
public static void main(String[] args) {
int x =17;
number(x);
System.out.println(x);
why is the value printed out still 17 and not 42? Thanks!
The line
number(x);
passes the value of x into number. Nothing that links back to x is passed at all. Inside number, the x argument you've declared is not in any way linked to the x variable in main; it just receives the value that you passed into number. Assigning to the argument (x = 42) just changes the value of the argument, not the variable in main.
This is called pass-by-value, meaning that whenever you pass a variable into a method, the value of that variable is passed, not anything about the variable itself. Exactly the same thing happens here:
x = 17;
y = x;
y = 42;
System.out.println(x); // 17
System.out.println(y); // 42
y = x just takes the value of x and puts it in y. There's no ongoing link between x and y.
So how would you change it? The usual approach is have number return a new value:
int number(int val) {
return val * 2;
}
Then in main:
x = 17;
x = number(x);
System.out.println(x); // 43
Sometimes, people get confused by pass-by-value when it involves object references. Variables directly contain primitives like int, but they don't directly contain objects; they contain object references. So consider:
List<String> l1 = new LinkedList<String>();
Now, l1 contains a value that is a reference to the linked list object. Now suppose we do this:
List<String> l2 = l1;
What happened there? Do we have one list, or two?
The answer is, of course, one: The value we copied from l1 to l2 is the reference to the list, which exists elsewhere in memory.
Key points in summary:
When you pass a "variable" into a method, it's the value of the variable that gets passed (always — Java is purely pass-by-value [some other languages have something called pass-by-reference, where a reference to the variable is passed, but Java doesn't have that)
The same thing happens when you assign a variable to another variable
Object references are values that tell the JVM where the object is in memory
Java is pass by value So when you passes x which is defined in main() to number() method ,only the value is copied to function parameter x and no address is passed unlike C pointers.So the value you get is 17 because it is not changed.

Outcome of this simple java program?

public class NotActuallyImmutable {
private final int x;
public NotActuallyImmutable(int x) {
this.x = x;// line 1
}
public int getX() {
return x;
}
}
public class Mutable extends NotActuallyImmutable {
private int x = 123;
public Mutable(int x) {
super(x);
}
public int getX() {
return x++;
}
}
now in my main class
NotActuallyImmutable n = new Mutable(42); // line2
int x = n.getX();
System.out.println("x is"+x);
I am expecting the output as 42 but it return the output as 123. I am expecting 42 because at line 2 I am making object of class Mutable and then at line 1 I am setting value as 42. so when i do n.getX() I should get the this latest value not the default 123. I know Ii am missing something but not able to figure out the logic behind it?
The problem is that the field x in Mutable and the field x in class NotActuallyImmutable are not the same. The x that is returned by getX() is the one in Mutable (because the getX() that is invoked is Mutable.getX(), not NotActuallyImmutable.getX()).
Note that if you removed the instance field from Mutable, then you would have a compiler error because NotActuallyImmutable.x is private to NotActuallyImmutable and not accessible to any code in Mutable.
If you made NotActuallyImmutable.x a protected field, then Mutable.x would shadow it and you would still have the same behavior. If you removed Mutable.x in this case, you would still have a compiler error because you were trying to increment a final field.
If you remove Mutable.getX(), then the x that would be returned by getX() would be NotActuallyImmutable.x, despite there being another field of the same name in Mutable.
The private int x in Mutable and the private int x in NotActuallyImmutable are completely different fields that just have the same name.
This isn't a problem for the compiler because you can't access a private field from another class. So as far as the compiler is concerned, when you define Mutable, the x in NotActuallyImmutable is invisible and might as well not exist.
It is of course confusing for the programmer. If you rename one of the fields to y (and the getter method to getY) the behaviour seems much more intuitive.
NotActuallyImmutable n = new Mutable(42); // line2
This means you have an object of type NotActuallyImmutable but the instance of created object is Mutable.
so in this code your dealing with Mutable object which will return 123. as the number you passed is saved in NotActuallyImmutable not in Mutable,
n has two different x values which are visible in different contexts, the parent class's private member variable and the child class's private member variable.
NotActuallyImmutable n = new Mutable(42); // line2
Creates a new Mutable. Executes parent(x) which sets the parent class's x to 42.
int x = n.getX();
n is a Mutable instance so this calls Mutable's getX() which returns Mutable's value for x (123) rather than the parent's.
I agree with Nice explanations given in above answers. But to to just brief the final understanding. As i am doing new Mutable(42).getX(), jvm first will look in Mutable object to get the value of X not inside NotActuallyImmutable. If i remove getX() method from Mutable , i get the expected(as per my expectation) value i.e 42.
This example gets messy becoz variable name i.e X is same in parent and child class but good for understanding concept

Java pass by reference and compiler optimization

In the function fermatFactorization(), a and b are being passed as reference parameters, since I am using the Long Class. However, in function testFermatFactorization() when I pass a and b to fermatFactorization(), the values of a and b do not get changed, and so testFermatFactorization() prints (0)(0). I tested this by printing out a and b in fermatFactorization(), and I got the output that I expected.
What am I overlooking? Could the compiler alter a and b in fermatFactorization() since they are only being assigned to?(doubtful)
public static void fermatFactorization(Long n, Long a, Long b)
//PRE: n is the integer to be factored
//POST: a and b will be the factors of n
{
Long v = 1L;
Long x = ((Double)Math.ceil(Math.sqrt(n))).longValue();
//System.out.println("x: " + x);
Long u = 2*x + 1;
Long r = x*x - n;
while(r != 0) //we are looking for the condition x^2 - y^2 - n to be zero
{
while(r>0)
{
r = r - v; //update our condition
v = v + 2; //v keeps track of (y+1)^2 - y^2 = 2y+1, increase the "y"
}
while(r<0)
{
r = r + u;
u = u + 2; //keeps track of (x+1)^2 - x^2 = 2x+1, increases the "x"
}
}
a = (u + v - 2)/2; //remember what u and v equal; --> (2x+1 + 2y+1 - 2)/2 = x+y
b = (u - v)/2; // --> (2x+1 -(2y+1))/2 = x-y
}
public static void testFermatFactorization(Long number)
{
Long a = 0L;
Long b = 0L;
fermatFactorization(number, a, b);
System.out.printf("Fermat Factorization(%d) = (%d)(%d)\n", number, a, b);
}
Java is pass by value. If you assign a new value to the argument, it won't affect the value in the caller method.
You have two options:
make your method return a and b - either in a int[] or using a separate FactorizationRezult class that has two fields. That way you will declare a and b as local variables in your called method, rather than taking them as parameters. This is the most advisable approach.
An alternative approach is to use a MutableLong and use a setValue(..) method - that way the changes will affect the object in the caller method. This is less advisable
a and b are references, not 'reference parameters', and they are passed by value. The values are changed in the called method but that has no effect on the caller.
There is no 'pass by reference' in Java.
In Java, everything is passed by value. There is no call-by-reference. Even when you pass an Object, it's reference is passed by value. So, when you pass a Long object, you are simply passing the reference to it by value.
Long, just like other primitive type wrappers, is "immutable". You can't change the long value it has inside. So, if you don't want to change your design, you have to make a mutable wrapper for long yourself (or use MutableLong) and pass it on. Changing your design to return the results instead of changing the method arguments is a much better way if you ask me.
Using the = operator clears out the spot in the memory where the local variable is stored and replaces it. This will not affect the original variable. Pass by value only allows you to modify data in in object (like modifying a field in it), not it's actual reference.

Java - Reference primitive data-type?

I know that with the following, a reference is made
public class MyClass
{
public Integer value;
}
public class Main
{
public static void main( String[] args )
{
MyClass john = new MyClass();
john.value = 10;
MyClass bob = john;
bob.value = 20;
System.out.println(Integer.toString(john.value)); // Should print value of "20"
}
}
But how do you do similar referencing with primitive data-types?
public class Main
{
public static void main( String[] args )
{
Integer x = 30;
Integer y = x;
y = 40;
System.out.println(Integer.toString(x)); // Prints "30". I want it to print "40"
}
}
Simple answer: you don't. Primitive values are always passed by value (i.e. they are copied).
Wrapper objects like Integer are also immutable, i.e. y = 40 will create a new Integer object with the value 40 and assign it to y.
To achieve what you want you need a container object whose value you can change.
You could, for example, use AtomicInteger:
AtomicInteger x = new AtomicInteger(30);
AtomicInteger y = x;
y.set( 40 );
System.out.println(x.get());
You cannot. While Integer is not a primitive datatype but a wrapper class around the int primitive type, your code is equivalent to:
Integer y = x;
y = new Integer(40);
So you are actually changing the object y points to. This mechanism is called auto-boxing. There's a simple rule of thumb: in order to change the state of an object, rather than to replace the whole object, you have to call one of your object's methods. It's quite common for classes representing values, such as numbers, not to provide such methods, but to require that the object be replaced by a new one representing the new value.
What happens in your second code block is that 30 gets boxed into an Integer and assigned to x. Then you assign that same Integer to y. x and y are now pointing to the same object. But when you do y = 40, that 40 is boxed into a new Integer object and gets assigned to y. The Integer class is immutable, you won't be able to change its value after creation.

Categories