I have the following code
class sample
{
public void update(List l)
{
l = null;
}
public static void main (String[] args)
{
List m = new ArrayList();
m.add("suresh");
m.add("sankar");
new sample().update(m);
System.out.println(m);
}
}
The answer will be {["suresh,"sankar"]}. The m is a pointer to the arraylist object, it contains an memory address value (for ex consider 0xf34 ). when we pass m to update method ,the local variable l will be set to 0xf34 that points to arraylist object in memory .when we set null to this variable l , the memory address replaces the arraylist with null ,hence the variable m should also refer null.am i right.please help.
No, the compiler has it right. :)
The parameter l contains a reference to the ArrayList object assigned to m. l gets updated to null, and indeed any later use of lwithin the update() method would see it as null. But l is a separate variable that has scope only within that method -- it's not linked to m in any way (other than the fact that they originally contained references to the same object).
The key to understanding this is to remember that all objects are accessed indirectly via a reference. When an object is passed as an argument the method, the "value" actually being passed is a reference, and not the object itself.
When you null out the l parameter in the update method, you are setting that specific reference to null - the original reference m remains unchanged, and the object referred to by both references is also unchanged.
If you know C/C++, then this can be paraphrased as:
void update(List* l)
{
l = NULL; // set the pointer to null - the object (*list) is unmodified
}
void main()
{
List* m = ...;
update(m);
printf(m->values());
}
The pointer m is copied by value. The object pointed to (the list *m) is not altered in any way. The value of the pointer is copied from m to l. When l is set to NULL, that is a local change that only affects the value of the l pointer.
Here's an example where pass by reference involves a non-local change,
class NonLocalChange
{
public void change(int[] i) {
i[0] = 2;
i = null;
}
public static void main(String[] s) {
int[] m = new int[1];
m[1] = 3;
change(m);
System.out.println(i[0]);
}
}
The result printed is 2. This is because the change method changes the object referenced by l, and not just the reference itself.
Note that this doesn't throw a NullPointerException, even though l is assigned to null. As before, it's a reference, and so it's a local assignment to the value of that reference.
Your update method just sets the local l reference to null without changing anything about the passed-in object.
just imagine that you have a address (X for example) in your heap.
if you set m to refer to X as well as l to refer to X. we have two variable referring to same address, if you change one of them to null, the other one will remain as old value.
Lets say, new ArrayList() returns address 2000 in which the new ArrayList object is stored.
List m = new ArrayList():
lets say, m # 9999 = 2000, here let the number following '#' indicates the address at which 'm' is stored and the number following the '=' represents the value of 'm' (that would be an address as well since it is a reference type). So now 'm' at address 9999 holds 2000 which is the address of the newly created ArrayList object.
update(m):
Since Java is call-by-value always, it calls the update() method copying the value stored in m which is 2000. So now the parameter 'l' in update() definition holds the value 2000 (which is also the address of the previouly created ArrayList object). So we can say,
l # 8888 = 2000 ('l' at address 8888 holds the value 2000)
l = null:
So now, l # 8888 = null
System.out.println(m):
What is the value of m now? it is still 2000. The update() method didn't change the value of m. The method has just changed its local variable 'l' value. so 'm' still refers the previously created ArrayList object and is being printed.
No, you're not right. Java, as many other high level languages, employs call by sharing.
You could think of it like that: the reference to the actual argument is passed by value. Which means that within the called function, the reference initially points to the same value, thus any changes to the value itself are visible outside the scope of the called function, but any changes to the local reference are not. It is as if a copy of the address was passed.
Some additional reading for those interested.
objects and primitives
java+pass+by+value search
Related
First of all, I understand what's so called passing by value in Java.
Also I understand, when you pass an object or an array, it is the array's address that is passed into the method. So modifying the array variable inside the method will affect the outside array variable.
For example,
private void change(int[] a) {
a[0] = 1234;
}
public static void main(String[] args) {
int[] a = new int[2]{1,2};
change(a);
System.out.println(a[0]);
}
The output will be 1234, because the a inside change is actually the array outside.
What I don't understand is the following code:
private void change(int[] a) {
a = new int[3]{1234, 4, 5};
}
public static void main(String[] args) {
int[] a = new int[2]{1,2};
change(a);
System.out.println(a[0]);
}
Why the output is 1, not 1234?
The inside a was the same thing as outside a, right? I also modify the inside a just like the example above did, why two different output?
This is not the same. In your second example, you are changing the local reference a to refer to a completely new array, not changing the existing array. But this does not change the a in main to refer to the new array; it still refers to the old array, so 1 is printed.
If you wanted to re-assign a completely new array to the a in main using a method, then return the new array from change and assign that to a in main.
Let's inspect your function:
private void change(int[] a) {
a = new int[3]{1234, 4, 5};
}
As you stated in your question, a is a reference to an array. If you use it to modify the array (e.g., a[0]=1234), you will be changing the same array that was passed in to the function.
However, if you change the reference itself, a will no longer be pointing to the original array, and changes to it will not affect the original.
This is exactly because the reference is passed by value. We'll represent object pointers with 5-digit numbers like 12345. The process is as follows:
We create an int[]{1,2}, at memory location, say 10000. We assign a the value 10000. a is on the stack frame corresponding to main.
We pass the value 10000 to change.
change executes:
change creates a new array at location 20000 and sets the value of a on its stack frame to 20000. This does not affect the main stack frame.
change returns (void).
We deference the untouched pointer to the original array in order to print the zeroth element, 1.
Note that by the time change returns, we have no live references left to {1234, 4, 5}.
In Java all variables are references to objects.
When you pass a variable into an array, you pass the reference to the object. If you modify the object then the calling method - which also has a variable that refers to the same object - sees the change.
When you write "a = new int..." you are changing the value of the variable a to point to a different object. It is no longer referring to the same object as the one in the method that called it. So the calling method and the called method see different things.
When you pass a parameter by value, it basically means that it's copied from a method's point of view. So, you have a reference a to an array, and when you pass it to some method, inside that method you have another reference, also named a to the same array. Now, when you assign a new value to that reference (a = new int[]...) you are only modifying the local a variable to point to a new array.
The answer has as much to do with passing by reference or value as it does with which variables are in scope when you attempt to make the change.
When you pass "a," or any variable to a method, you pass the value of that variable - in other words a copy of what it represents- and not the actual variable itself. For example:
public static void main(String[] args){
int a = 3;
addTwo(a);
System.out.println(a);
}
private void addTwo(int a){
a += 2;
}
In the above example the value 3 is passed to addTwo. The variable "a" in the main method is outside of its scope (i.e. it is localized to the main method) so the addTwo method acts only on the copy of "a," the value 3, and not the variable. The variable "a" remains unchanged. When the method completes the value of a is discarded and the original "a" in the main method remains unchanged.
This is the same thing that is happening in your case. It does not matter that you use the same name for two variables. The variable in your main method will not be changed.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
Ok, so I am a relatively new programmer. I have read over and over about passing variables. From what I have read here is what I've come to understand: In Java, when you pass a variable to a method (be it primitive or Object) you are ALWAYS passing by value. But what you are REALLY doing is passing a copy of the reference to an object or variable in memory.
So why do they call it pass by value? It seems to me you are passing by reference. Also, in C when you pass a pointer to a function, aren't you passing the address of a variable in memory? Yet it is called pass by value. What am I overlooking? Can someone please explain and clarify why I this? I know how to pass variables and such and I have read several SO posts on this but I am not fully satisfied yet. Consider an example:
static void setNameStatic(Dog d, String name) {
d.name = name;
}
public static void main (String args[]) {
Dog d = new Dog("dog1");
System.out.println( d.getName() );
setNameStatic( d, "dog2" );
System.out.println( d.getName() );
}
Won't this output: dog1 and dog2. So aren't you going to where the reference is referring to and changing data around? What exactly does the value have to do with here? Any helpful comments are appreciated. And yes, I know it is pass by value, but why isn't it called "pass by sending copy of reference" lol?
Update: Thanks to everyone that gave a helpful answer. I know this was marked duplicate, and sorry about that. I am satisfied with the answers now.
Your memory looks like this at the moment of:
Dog d = new Dog("dog1");
Stack (with local vars) Heap
+-----------+ points to
| Dog d | ---------------> real dog object
+-----------+
| ... |
+-----------+
| ... |
+-----------+
And then, when you pass in a reference to a method, it looks something like this (where the Dog dog2 is the method argument):
Stack (with local vars) Heap
+-----------+
| Dog d | ---------------> real dog object
+-----------+ ^
| ... | |
+-----------+ |
| Dog d2 |------------------------------
+-----------+
So, the reference is passed by value. It points to the same object but it is the new reference!
Meaning, if you would try something like this:
public static void main(String ... args) {
Dog d= new Dog("dog1");
setNameStatic(d, "dog2");
System.out.println(d); // Still prints dog1 !!!
}
static void setNameStatic(Dog d2, String name) {
d2= new Dog(name);
}
Because the new (copied) reference now points to the new object on heap and the original object has not changed.
Because the value of any variable of reference type is its address in memory.
Because the value of any variable of primitive type is its value itself.
So you always pass values of variables.
Every variable is passed by value. In the instance of primatives, we have the naive case - the values are passed into the function.
In the instance of Objects, we have a slightly more complicated although analogous paradigm - the references to the objects are passed by value.
Note the subtle differences:
//This is essentially a no-op. The values are only local to the function
void swap(int a, int b){
int temp = a;
a = b;
b = temp;
}
//This is different. The references to a and b are passed by value so the values of a.x and b.x are actually swapped on return.
void swap(Point a, Point b){
int temp = a.x;
a.x = b.x;
b.x = temp;
}
Passing by value means that the value is transferred to method, i.e. yet another copy of the same value is created:
int i = 5; // one copy of 5
foo(i);
private void foo(int n) {
// here n is 5, however it is "another" 5
}
The evidence of passing by value is that you cannot change your i from within the method foo():
int i = 5; // one copy of 5
foo(i);
// i is still 5 here
private void foo(int n) {
n = 6;
// n is 6, however it is actual inside the method only.
}
The same is with objects, however in that case reference is passed by value.
Also, in C when you pass a pointer to a function, aren't you passing the address of a variable in memory? Yet it is called pass by value.
No it is not. When you pass a pointer to a value to a function in C, it is known as 'pass by reference'. The function can directly access & modify the original value because it has it's address. Pass by value is when you pass the value of objects instead of their locations or addresses. Look at the following examples.
int addOne(int x)
{
return x + 1;
}
void destructiveAddOne(int *x)
{
*x += 1;
}
int main(void)
{
int x = 5;
int y = 5;
// We pass the _value_ of x, ie, 5 to addOne, and store the result in z.
// The value of x will remain unchanged, ie, 5.
int z = addOne(x);
// We pass a REFERENCE to y, ie, it's address to destructiveAddOne()
// destructiveAddOne then modifies the value of y to be y + 1. The value of y
// has now CHANGED to 6. This is call by reference.
destructiveAddOne(&y);
return 0;
}
A variable holds the bits that tell the JVM how to get to the referenced Object in memory (Heap).
When passing arguments to a method you ARE NOT passing the reference variable, but a copy of the bits in the reference variable. Something like this: 3bad086a. 3bad086a represents a way to get to the passed object.
So you're just passing 3bad086a that it's the value of the reference.
You're passing the value of the reference and not the reference itself (and not the object).
This value is actually COPIED and given to the method.
Had that before:
Is Java "pass-by-reference" or "pass-by-value"?
It is a tricky thing to get your head round. I think of it as real numbers, albeit abstracted. Say your first dog, dog1, is created at memory location "100,000" (I know but bear with me). You pass the reference's value of 100,000 around to methods. Your method changes the name of the object living at 100,000.
If you pass your dog1 object into a method that does d = new Dog("dogXXX"), then it will work with a brand new object at (say) 200,000 leaving your dog1 at memory address 100,000 unchanged.
Apologies for the memory address abuse which will have experts spitting their coffee...
In java you're passing parameters by value to the methods, but the parameters are themselves ref type if the parameter is an object.
As a contrast in a programming language like C that passing by reference is allowed, if you print a reference you get something different from what you get when print it's value.
To insure that objects are reference types and compare them with primitives, Try this:
public class TestClass {
public static void main(String[] args) {
String s = new String("a");
String t = new String("a");
System.out.println(s==t);
char a = 'a';
char b = 'a';
System.out.println(a==b);
}
}
The result is :falsetrue
References in Java are passed by value of the reference.
When you pass reference as a method parameter copy is created and you operate on this copy.
To illustrate it have a look at this sample code:
final Person person = new Person();
person.setName("A");
changeName(person, "B");
System.out.println(person.getName());
Now if we have changeName implemented as this:
private static void changeName(Person person, String name) {
person.setName(name);
}
Then the result is B. It's because copy of the reference still points to the same object and there is possibility to modify it.
On the other hand if you change the changeName method to this:
private static void changeName(Person person, String name) {
person = new Person();
person.setName(name);
}
Then the result is A. It's because copy of the reference points to the new object, but original reference still points to the original object and it's value is not modified.
If Java would pass object references by reference than the result would be B, because it would operate on the original object.
When you pass an object as a parameter in Java, you actually pass a reference, and the reference is the value used in the stack. However, any assignment you make to this reference inside the method will not be observed by the caller, because you only change a copy of the reference. Same goes with primitive values as parameters.
In other languages (like C++), you have the option to pass by reference, allowing you to change the reference itself from within a method. In Java, for example, you can't implement a swap method that takes two parameters and swaps them. In C++ it's possible.
I am trying to understand the difference between Object with primitive variables when using them as parameters in a method.
There are some examples using reference variables:
public class Test1 {
public static void main(String[] args) {
int[] value = {1};
modify(value);
System.out.println(value[0]);
}
public static void modify(int[] v) {
v[0] = 5;
}
}
result: 5
public class Test2 {
public static void main(String agrs[]) {
Integer j = new Integer(1);
refer(j);
System.out.println(j.intValue());
}
public static void refer(Integer i) {
i = new Integer(2);
System.out.println(i.intValue());
}
}
result: 2 | 1
So what is different in here?
In java array is primitive type.and Integer is Object type.
For primitives it is pass by value the actual value (e.g. 3)
For Objects you pass by value the reference to the object.
In first example,
you are changing value in array.
while in other example ,
you are changing reference of i to other memory location where object value is 2.
when returning back to main function, as you are not returning value. its reference scope limited to "refer" method only.
Recall that the array references are passed by value. The array itself is an object, and that's not passed at all (That means that if you pass an array as an argument, your'e actually passing its memory address location).
In modify() method, you're assigning 5 to the first place in the array, hence, changing the array's value. So when you print the result, you get: 5 because the value has been changed.
In the second case, you're creating a new Object of type Integer locally. i will have the same value when you exit the method refer(). Inside it you print 2, then you print i, which is 1 and hence change doesn't reflect.
v[0] = 5, is like saying Get 0th element of current v's reference and make it 5.
i = new Integer(2), is like saying change i to 2's Integer object reference
In one case you are changing the internal values via the reference and in latter you are changing the reference itself.
The difference here is that they are different.
In your first example you are passing the argument to another method, which is modifying one of its elements, which is visible at the caller. In the second case you are assigning the variable to a new value, which isn't visible at the caller, because Java has pass-by-value semantics.
NB 'Primary variable' has no meaning in Java.
I don't know what the word 'advance' in your title has to do with anything.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
public class StackOverFlow {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("A");
al.add("B");
markAsNull(al);
System.out.println("ArrayList elements are "+al);
String str = "Hello";
markStringAsNull(str);
System.out.println("str "+ str);
}
private static void markAsNull(ArrayList<String> str){
str.add("C");
str= null;
}
private static void markStringAsNull(String str){
str = str + "Append me";
str = null;
}
}
This outputs:
ArrayList elements are [A, B, C]
str Hello
In the case of ArrayList, the added elements are getting retrieved.
In case of String the method call has no effect on the String being passed. What exactly is the JVM doing? Can anyone explain in detail?
In the case of Arraylist string objects the added elements are getting retrived. In case of String the method call has no effect on the String being passed.
It happens cause Java is Pass-by-Value and Strings are immutable
When you call
markAsNull(ArrayList<String> str)
The a new reference by name str is created for the same ArrayList pointed by al. When you add an element on str it gets added to same object. Later you put str to null but the object has the new values added and is pointed by a1.
When you call
markStringAsNull(String str)
{
str = str + "Append me";
// ...
}
The line str = str + "Append me"; creates a new String object by appending the given string and assignes it to str. but again it is just reference to actual string which now pointing to newly created string. (due to immutablity) and the original string is not changed.
The markXAsNull methods are setting the local references to be null. This has no effect on the actual value stored at that location. The main method still has its own references to the values, and can call println using those.
Also, when doing the string concatenation, toString() is being called on the Object, and that is why the ArrayList is outputted as a list of its values in brackets.
From the Book: SCJP - Sun Certified Programmer for Java 6 Study Guide (Katty Sierra - Bert Bates) Chapter 3 Objective 7.3 - Passing Variables Into Methods
Java is actually pass-by-value for all variables running within a single
VM. Pass-by-value means pass-by-variable-value. And that means, pass-by-copy-ofthe-
variable!
The bottom line on pass-by-value: the called method can't change the caller's
variable, although for object reference variables, the called method can change the
object the variable referred to. What's the difference between changing the variable
and changing the object? For object references, it means the called method can't
reassign the caller's original reference variable and make it refer to a different object,
or null. For example, in the following code fragment,
void bar() {
Foo f = new Foo();
doStuff(f);
}
void doStuff(Foo g) {
g.setName("Boo");
g = new Foo();
}
reassigning g does not reassign f! At the end of the bar() method, two Foo objects
have been created, one referenced by the local variable f and one referenced by
the local (argument) variable g. Because the doStuff() method has a copy of the
reference variable, it has a way to get to the original Foo object, for instance to call
the setName() method. But, the doStuff() method does not have a way to get to
the f reference variable. So doStuff() can change values within the object f refers
to, but doStuff() can't change the actual contents (bit pattern) of f. In other
words, doStuff() can change the state of the object that f refers to, but it can't
make f refer to a different object!
Java follows passby value concept ( there is no pass by reference in java ) . So when you pass a string to the function it sends a "copy of reference" to that string to the function. So even if you set the variable to null in the function, when it returns to the caller it refers its original value only. That's why original string has no effect.
In case of Arraylist, copy of reference refers to the original Arraylist (which is also the same in case of string). But when you add something into ArrayList, it refers to the original object and so that you can see the effect. ( try in method arraylist=new ArrayList(), your original arraylist will remain as it is).
In case of string, when you do
str=str + "abc";
Java creates a new String object which will have reference to string "xyzabc" ( e.g. str="xyz") and "xyz" will be eligible for the garbage collection. But as "xyz" is still having an variable which refers to it it ( original string) will not be garbage collected. But as soon as the function call gets over "xyzabc" goes for garbage collection.
Summary of the discussion is, as long as an reference refers to the same object you can make changes in the function, but when you try to change the reference ( str=str+"abc") you are refering to the new object in the method so that your original object will remain as it is.
In Java, you may create one object, and referenced by multiple pointers. Calling a mutator method on any pointer will effectively modify the sole object, thus updating all other references.
But if you call variable assignment statements on a reference, only that pointer will be changed, since it doesn't do any object side work (this is the best I could explain...).
Passing an object to a parameter will effectively copy the reference, resulting in a single object, with two pointers - one global, and the other local.
One more point, since String is immutable, you'll actually get a new object, that is distinct from the original (from the fact that you have to say a = a + "a"), that's why it won't modify the original string.
I read that Java does everything by call by value. I was wondering how to verify this fact? As far as I understand, in case of objects(not primitives) functions get its own copy of reference but points to same object. In that case, reference of that object in callee function and caller function should be different? How can I verify that? In other words, how to print the reference of the object.
System.out.println(object); //does this print reference i.e text following #
EDIT:
I understand that modifying object in callee function does change the value in caller function. I am interested in how to print the references of objects as in what property can I print on console that clearly shows me 2 different reference.
Java passes references by value. This means you'll get a copy of the reference, so once you dereference that you'll get to the same object in the heap as with the original reference.
But if Java was pass by reference:
public static void nullify(Object obj) {
obj = null;
}
public static void main(...) {
String x = "Hello";
nullify(x);
System.out.println(x);
}
The call to S.o.p. would print null if Java was pass by reference. But it isn't, so x is unchanged and you'll get Hello.
Assuming Class A property aa
A a= new A();
a.aa = 1;
// print a.aa here should be 1
method(a);
// here a.aa should be 2
Void method(A a) {
a.aa =2;
a = new A();
a.aa = 3;
}
So this shows reference was passed as value. When you change the object in the method it does not change the reference of caller.
I think the String Object#1ed3af is composed of the class name of your object and it's hashcode, separated by a #. This is a unique string, identifying it.
Read this topic to get a full explanation !