I am new to Java.
I tired the following java code
public class A {
int x;
public static void main(String[] args) {
A a1= new A();
a1.setX(5);
A a2=a1;
System.out.println(a1.getX());
System.out.println(a2.getX());
a2.setX(10);
System.out.println(a1.getX());
System.out.println(a2.getX());
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
I thought the output will be
5
5
5
10
But when I compile and run the code the output is coming as
5
5
10
10
Why the a1 x value is changing with a2 x?
A a2=a1;
This statement causes the a2 variable to represent the same location in memory that a1 represents. Therefore, any changes you make to the object at this memory location are changing the same pieces of memory as if you had been making those changes to a1.
If you want a2 to point to a different memory location, you'll need to allocate memory to hold the new value, like you did with a1:
A a2 = new A();
Objects in java are defined by reference. this means that when you do a2 = a1 what it means that a2 points to the same instance as a1. this means that changing one changes the other as well
You've declared an object called a1. and set it's value to 5. so its name = a1, value = 5. Let's pretend the address of a1 is 0x123.
Then you've declared an object called a2, and told it it has the same address as a1. when you said a2 = a1. Therefore whatever is in a1 (to start with, 5) will be pointed to by a2 also. And the address of a1 and a2 is, in both cases, 0x123.
Then you set the value in a2 to 10. In other words the value at address 0x123 will be 10. but a1 also has the address 0x123, so it doesn't matter whether you print a1 or a2, they both point to the value 10 that is in the same memory location at 0x123.
It's like the value is in a box which happens to have two different names on it, but it's still the same box with the same address and therefore with the same content.
I hope that helps.
Related
I would like to understand how primitive and object reference variable behaves differently. I have used the below code from OCA/OCP Java SE7 by Kathy Sierra as an example:
public class VariableTesting {
public static void main(String[] args) {
int a = 10;
System.out.println("a= " + a);
int b = a;
b = 30;
System.out.println("a= " + a + " after change it to b and b is " + b);
Dimension a1 = new Dimension(5, 10);
System.out.println("a1.height = " + a1.height);
Dimension b1 = a1;
b1.height = 30;
System.out.println("a1.height= " + a1.height + " after change to b1");
}
}
In the above piece of code, I'm getting the value of a = 10; before and after changing the value of b.
The output for the primitive variable case is:
a = 10
a = 10 after change it to b and b is 30
However, in object reference variable I'm getting a different value once I change the value of b1.height = 30;
The output for the reference variable case is:
a1.height = 10
a1.height = 30 after change to b1
It is mentioned in the book that in both case the bit pattern is copied and a new copy is placed. If this is true, then why we are getting different behavior?
This is the underpinning difference between a reference and a primitive. In both cases, you're getting the actual value, but only in the case of an object do you have a chance to impact the result of any other usages of it.
Let's walk through the code.
int a = 10;
int b = a;
These two declarations are saying the following:
Assign the value 10 to an int identifier called a.
Assign the value of a to an int identifier called b.
So far, so good. Nowhere do we say that a is referenced by b; we're only taking values.
If we declare:
b = 30;
We're saying take the value of 30 and assign it to the identifier b.
We don't do anything with a at that point; it already contains the value 10. This is why a and b are different.
Now, when we get to the object, things don't really change on the surface...
Dimension a1 = new Dimension(5, 10);
Dimension b1 = a1;
We translate this as:
Assign the value of instantiation of a new Dimension with (int) parameters 5 and 10 to a Dimension identifier a1.
Assign the value of a1 to a Dimension identifier b1.
We're still assigning values here, since Java is pass-by-value. The kicker here is that in Java, the value of an object is still a reference to that object.
By the above example, a1 and b1 are pointing to the same instance.
Now, when we state this:
b1.height = 30;
We're actually saying:
Assign the value 30 to the field height dereferenced through the value b1.
We're still referring to the value of b1 here, which is tied to a1. This is why you see the difference; because a1 and b1 refer to the same value (which is the same reference), any change done through the identifier b1 is reflected through a1.
There is only one instance
When you say
Dimension b1= a1; // <-- assigns reference of a1 to b1.
you assign the reference address that a1 refers to to b1. Thus, when you modify the height field through b1 you also modify a1.
b1.height=30; // <-- a1.height = 30
Create another instance
If you want b1 to be a unique referene, then you use new.
Dimension b1= new Dimension(a1.width, a1.height); // <-- creates a new Dimension
So I've got this piece of code,
package test1;
class Student13
{
public static void main(String [] args)
{
Student13 p = new Student13();
p.start();
}
void start()
{
long [] a1 = {3,4,5};
long [] a2 = fix(a1);
System.out.print(a1[0] + a1[1] + a1[2] + " ");
System.out.println(a2[0] + a2[1] + a2[2]);
}
long [] fix(long [] a3)
{
a3[1] = 7;
return a3;
}
}
Can you tell me why it returns 15 15 and not 12 15? Function fix is applied only for long[] a2, so how come that the final result is 15 15?
You pass the a1 array to fix(), which is called a3 in the fix() method, but is regardless still referencing a1. So when you update a3: a3[1]=7, you actually update the paramater value of fix() which was a1. Thus you updated a1!
In the line
long a1[] = { ... };
you are creating one array object. This will be the only one throughout the rest of the program.
Now the call to
fix(a1);
assigns a reference to exactly that array to the parameter a3 in this fix method. As this method returns this reference (return a3;), the line
long[] a2 = fix(a1);
will assign the same reference to the variable a2. So at all points, all variables and parameters referred to the same array.
The fix method is modifying that array. So the modification is seen by all aliases you have.
Reference of a1[] is passed as a parameter to fix() that's why basically
a1[] == a2[] after calling fix().
a2[] is pointing to a1[] but a1[] sum is now 15, so a2[] sum is also 15.
I have a below code. The variable c and d are class variables and initially they were pointing to value 0, but when I did c=a* a; and d =b* b*b they printed value as 25 and 64 which is correct. so what I think now is that the c and d are now pointing to value 25 and 64 and they are class variables, so if I do j=c+d; it should give me 89 as j value, but it is giving me 0... why? I know if I use static with c and d variable it will give me 89 value... but why I should use static as c and d are global variables and there values are now updated to 25 and 64. Please let me know. Thanks.
public class BaiscSum {
int a=5;
int b=4;
int c;
int d;
int j;
public void square() {
c=a*a;
System.out.println(c);
}
public void cube() {
d=b*b*b;
System.out.println(d);
}
public void sum() {
j=c+d;
System.out.println(j);
}
public static void main(String[] args) {
BaiscSum squ= new BaiscSum();
squ.square();
BaiscSum cub = new BaiscSum();
cub.cube();
BaiscSum su = new BaiscSum();
su.sum();
}
}
You are using three separate instances of your class. This means that squ, cub, and su each have their own version of the class. Instead, use the same one instance, so that all changes will happen to the same instance.
public static void main(String[] args) {
BaiscSum sum= new BaiscSum();
sum.square();
sum.cube();
sum.sum();
}
If I do j=c+d; it should give me 89 as j value, but it is giving me
0. why?
Because you are referencing sum() with su object but you have not called cube() and square() on su instead you called it with cub and squ respectively.
Change to
BaiscSum su = new BaiscSum();
su.square();
su.cube();
su.sum();
It will give you the expected output.
Since all the variables you are using are instace so every object will have its own set of variable on their respective memory spaces and if you changed any one objects variable it will not effects other objects value.
This could clear more
As an explanation every object is assigned a seperate memory and so changes to the variable of one objects doesn't effect changes to other objects variable unless they are static. So in the third object c and d is not initialized for su object so jvm uses default value if int ie 0 giving you a sum of zero.
I need your knowledge to explain something very simple that confuses me
As you can see, it's a very beginning practice on Java, and I already face the first confusions.
So the question is, what is true from the A, B, C, D?
A. line 12 prints 4
B. line 13 prints 9
C. line 13 prints 18
D. line 14 prints 18
I know that the answers are C and D but because I'm studying and I try to understand why, could you please explain this to me?
I first thought that the correct ones whas A and B but it comes out that I was wrong.
What is really going on with ob.t = ob2; ob2.t = ob; and whats the role of Test t; in the Class Test?
1 class Test {
2 Test t;
3 static int a;
4 Test(int i) { a = i; }
5 void xchange(Test ob, int i) { ob.a = i * ob.a; }
6 }
7 class Call {
8 public static void main(String args[]) {
9 Test ob = new Test(2); Test ob2 = new Test(3);
10 ob.t = ob2; ob2.t = ob;
11 ob.xchange(ob, 2); ob2.xchange(ob.t, 3);
12 System.out.println(ob.a);
13 System.out.println(ob2.a);
14 System.out.println(ob.t.a);
15 }
16 }
What's the role of Test t; in class Test?
It declares a field in Test of type "reference to Test". Note that variables and fields in Java cannot store objects; they can only store references to objects.
What is really going on with ob.t=ob2; ob2.t=ob;?
It sets the t fields of both Test objects to contain references to each other. So the first object's t field contains a reference to the second object, and vice versa.
It is tempting to say that "it assigns ob's t field to contain a reference to ob2", but strictly speaking this is incorrect, as ob and ob2 are not objects.
Could somebody please explain how this program is executed?
Here is the code whose output I just can't quite seem to get it:
class Box {
int size;
Box (int s) {
size = s;
}
}
public class Laser {
public static void main(String[] args) {
Box b1 = new Box(5);
Box[] ba = go(b1, new Box(6));
ba[0] = b1;
for(Box b : ba)
System.out.println(b.size + " ");
}
static Box[] go (Box b1, Box b2) {
b1.size = 4;
Box[] ma = {b2, b1};
return ma;
}
}
The actual output when I run this is 4, 4. But according to my understanding this should be 5, 4.
Can anyone please help understand how this is being executed?
I have added the comments for you;
The important TWIST that you missed here is;
Box[] ma = {b2, b1}; its not {b1,b2}. Memory locations are interchanged while returning.
public static void main(String[] args) {
Box b1 = new Box(5); // b1 == location A
Box[] ba = go(b1, new Box(6)); // ba == location B which stores Location A, D
// PLEASE NOTE HERE
// After the function go() is executed;
// ba[] will have {D, A}
// So ba[0] will have object b1 which is at location A.
ba[0] = b1; // location B will now store A and A
for(Box b : ba)
System.out.println(b.size + " "); // Output: 4 and 4
}
static Box[] go (Box b1, Box b2) { // go(location A, location D )
b1.size = 4; // A's object.size = 4
Box[] ma = {b2, b1}; // position is interchanged here (D and A)
return ma; // return the location of ma
}
Hope this helps.
Do let me know if you have any questions. Everything is pass by value in java. The memory addresses are passed by value.
When you pass an object as a parameter, you're actually passing a copy of a reference to it. That is, if you modify the parameter object inside the method, the object will retain those modifications when that method returns, which is why you see b1 retaining the size = 4 assignment after go returns.
Java always passes references to objects in method calls. When you're calling go, the first argument (b1), is a reference to the same b1 Box that you have in your main. You then modify that object, whose size is now 4.
The values passed to go are references to the objects. If you're coming from C, you can think of the parameters as having pointer types, something like
Box** go (Box *b1, Box *b2) {
b1->size = 4;
/* allocate an array of Box*, set it up, return it */
}
(Sorry if I got the C syntax wrong.) The pointers (references) themselves are passed by value, which means that if you say inside "go" (in the C program):
b1 = &some_other_box;
it doesn't affect any variables on the calling side, and it works the same way in Java. This makes it a bit different than a var parameter in PHP or Pascal.
Java passes copies of references to objects in method calls.
You can't change an object by assigning to it.
public static void main(String[] args) {
Box b1 = new Box(5);
Change(b1);
System.out.println(b1.size + " ");
static void Change(Box b1) {
b1 = new Box(6);
}
This will always return 5, because the function Change only overwrites the copy to the referenced object.
You can however affect the object's properties like so:
public static void main(String[] args) {
Box b1 = new Box(5);
Change(b1);
System.out.println(b1.size + " ");
static void Change(Box b1) {
b1.size = 6;
}
This will return 6 (the reference to the object remains unchanged).
If the function 'go' in the original post is in C (and b1 and b2 are C pointers), it can do the following two things (which the caller will see):
Change the value of variables in the data structures pointed to by b1 and b2.
Make the original b1 and b2 point to different data structures.
In Java, we can do 1 but NOT 2, since go does not have access to the original b1 and b2. (It has access to copies of b1 and b2. At the beginning of the subroutine, the copy b1 points to the same object as the original b1 and so on.)
Saying Java is pass by call DOES miss something, namely the ability of the function to do 1, i.e., change the properties of the object in the heap referenced by b1 and b2. [This is what happens in the statement, b1.size = 4;, which caused the original poster's confusion.]
b1 in 'go' is NOT the same location as b1 in 'main'. However, when the function starts, b1 in 'go' references the same object as b1 in 'main' and any changes made to the object using b1 in 'go' will be seen when b1 in 'main' is used as the reference.
However, if b1 in 'go' is set to another Box, b1 in 'main' will NOT see this; it will still see the previous Box.
In Java, objects are passed by reference, primitives are passed by value.
public class Laser {
public static void main(String[] args) {
//Create a Box of size 5.
Box b1 = new Box(5);
//Create an array of Box objects, which are the results of the go method
Box[] ba = go(b1, new Box(6));
// ba now looks like {new Box(6), b1 /*b1 is size 4 now*/}
// assign reference to b1 at index 0 in ba.
ba[0] = b1;
// array now looks like {b1, b1}
for(Box b : ba)
System.out.println(b.size + " ");
}
static Box[] go (Box b1, Box b2) {
//set the size of the first box to 4
b1.size = 4;
//create an array of boxes, with b2 in index 0 and b1 in index 1
Box[] ma = {b2, b1};
return ma;
}
}