Confused about Java passing methods (by value or reference) [duplicate] - java

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
guys,
Please, can you clarify something for me?
As i understand (please correct me if i am wrong), when i pass the variables to a method or class i'm passing by value, isn't it?
if it's true, then why does Java has method .clone()?
Why do i ask this question, because i am very confused...here is the code:
if i pass variables using the following code and then modify them inside the dialog, the original values (outside) are also changed.
DialogChoosePayment mDialogChoosePayment = new DialogChoosePayment(mContext, (ArrayList<Payment>) defaultValues.getPayment(), (ArrayList<Payment>) selectedValues);
mDialogChoosePayment.show();
But, if i use the following one, then the variables values (Original variables from outside) are not changed.
DialogChoosePayment mDialogChoosePayment = new DialogChoosePayment(mContext, (ArrayList<Payment>) defaultValues.getPayment().clone(), (ArrayList<Payment>) selectedValues.clone());
mDialogChoosePayment.show();
Please, explain it to a newbie =)

Source: http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html
Passing Primitive Data Type Arguments Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost.
Passing Reference Data Type Arguments Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level.

Java passes parameters by value. There are a lot of references on this topic. The most popular example is that you cannot simply implement method swap() that accepts 2 arguments and swaps their values.
The confusion may be caused by missunderstanding that the line like:
Object x = new Object();
indeed creates object but assigns reference to it to the variable x, so x is a reference. But if the you pass x to method you pass reference by value (or value of reference if you want).
This can give yo a tip why do we need method clone(). We need it when we want to create other object similar to the first one. Similarity means that it contains the same data and depends on the clone implementation (deep or not). But this is a absolutely another discussion.

Java has pass-by-value and only pass-by-value. At the same time Java has pointers (officially called references); so when't your passing an object to a method you're basically passing by value the variable that references that object.
If you modify the object then the object is seen to be modified at the called site. If you modify the reference to that the object in the called method, then this is not seen at the called site.
In your second case you create new objects with .clone() and pass them. Since there are no other references only in the called site, the changes can only be seen there.

when you pass (ArrayList<Payment>) defaultValues.getPayment(), you are actually passing reference to the array list. Any modifications using that reference will be reflected back to your list.
When you pass (ArrayList<Payment>) defaultValues.getPayment().clone(), you are creating a clone of the array list and passing reference to the cloned list. Any changes will be reflected only to the cloned array list not with the original array list.

In the first case you have copy of references to the objects. Surely you can change state of those objects.
In the second case you have copy of references too. But those references point to the new cloned objects.

Related

Java- passing Lists to methods working as pass by reference

There are lot of discussions in stackoverflow regarding pass by value and pass by reference. But i want to know what is happening in the following scenario?
This page says java is pass by value. Is Java "pass-by-reference" or "pass-by-value"?.
In case of following code, the the element is removed from the removeElement method , it is removing the 5th element from list when i print the list.
public class Load {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.addAll(Arrays.asList(1,1,2,3,5,5,13,21));
removeElement(list);
System.out.println(list);
}
public static void removeElement(List<Integer> list){
list.remove(5);//removes element at index 5
}
}
The output of the program is [1, 1, 2, 3, 5, 13, 21].
Can somebody explain how this is pass by value rather than pass by reference?
Java is always pass by value. The value of any variable of type Object is actually a reference. That's why, for example, == is said to be a reference comparison, and you need to use .equals() for comparing Object(s).
In case of primitives it purely pass by value and in case of Objects it is pass by value of the reference.
When you pass list from the main method to method removeElement() as an argument there is another (copy) reference that is created that points to the same List instance. Any changes made from either of the references will reflect on the same actual instance. However if you assign one of the reference to some new Object the other reference will still point to the same original instance.
Although this question asks (again) for the difference between "pass-by-value" and "pass-by-difference", I think there is an underlying misconception that causes so much confusion. This must be resolved:
As a matter of fact a method call passes all parameters by value. As Erwin Bolwidt pointed out in his comments, there are two kinds of types:
primitive types
reference types
The JLS (§4) states it:
The Java programming language is a statically typed language, which means that every variable and every expression has a type that is known at compile time.
[...]
There are two kinds of types in the Java programming language: primitive types (§4.2) and reference types (§4.3).
When speaking about "pass-by-value", it means that the content of a variable is passed by value when being used as a parameter for a method call. And the content of a reference typed variable is a reference. It is not the object that is referred to by a variable. That's a huge difference.
In your example, the content of the variable list is passed as value to the method removeElement. This value is the reference to the list object.
That further means that the method removeElement now has access to that list object (by its reference) and can manipulate it, for example remove an element. But it has no access to the content of the variable with which the method was called. So it cannot change the content of the variable list inside the main method (which would be possible with "pass-by-reference").

Java Functions Passing & Returning Complex Data Types

I'm in the process of learning Java and can't help but wonder how exactly Java passes function parameters and return values. I've done some search and found that Java only passes Objects by value. However, some people challenge this; they claim that when handling Complex Data Types (not Primitive like e.g. int) it only passes a pointer.
Does this mean that whatever changes are made to the local object affect the original one? Is there any way to pass "PURELY" by value (i.e. make a hard copy of an Object)?
Furthermore, what is true about the return value? For example, we use accessors (or getter functions - I'm not completely sure how they are called) to protect the private Attributes of an ADT from being changed to "illegal" values. If Java passes the Pointer, then whatever changes I make to the returned Object of an Accessor Function also affect the actual Attribute, if it isn't a Primitive Data Type, don't they?
Could anybody please help me clarify these concepts?
Thank you in Advance! :D
The key is to understand that Java passes everything by value. And this is also true for objects: It passes the pointers by values. So, it does not create a copy of the object, but of the reference.
The same goes for returning. So, yes, your thinking is right: you can modify the attributes (called class members) objects because they get returned in the form of a pointer. That is the reason why (if needed) someone could choose to design a class whose objects are is not modifiable once it is created.
I've done some search and found that Java only passes Objects by
value.
There is your confusion. You cannot "pass objects" in Java, because objects are not values in Java. The only types in Java are primitive types and reference types (references are pointers to objects). So the only values you can manipulate in Java are primitives and pointers to objects. All types are passed or assigned by value.

Are arrays in java pass by reference or pass by value?

Are arrays in Java pass by reference or pass by value?
Suppose I have an array called data that contains objects of some type. Now let us suppose that I pass and store that array in class A and then I pass it to class B and class B changes one of the entries of the array. Will class A's version of the array change? Does it matter if this was an array of primitives (such as int) instead? What about ArrayLists?
Everything in Java is pass-by-value. However, if you're passing a reference, it's the value of the reference.
Since Java methods can't reach into the caller's stack to reassign variables, no method call can change the identity of a reference (address) there. This is what we mean when we say Java is not pass-by-reference. This contrasts with C++ (and similar languages), which allows this in some cases.
Now let's look at some effects.
If I do:
Object[] o = ...
mutateArray(o);
the contents can be different afterwards, since all mutateArray needs is the address of an array to change its contents. However, the address of o will be the same. If I do:
String x = "foo";
tryToMutateString(x);
the address of x is again the same afterwards. Since strings are immutable, this implies that it will also still be "foo".
To mutate an object is to change the contents of it (e.g. successfully changing the last element of o, or trying to change the last letter of "foo" to 'd'). This should not be be confused with reassigning x or o in the caller's stack (impossible).
The Wikipedia section on call by sharing may shed additional light.
Arrays, like all other objects, are pass by reference (technically, you are passing a reference by value, but from the objects point of view, it is passed by reference). If you pass an array to a method and the method changes the array, the caller will see the changes. If you want to avoid having your copy modified, you need to copy it yourself. It doesn't matter whether the array contains primitives or objects. In general, this is the behavior you want, since passing by value would involve unnecessarily copying the (potentially large) array every time you use it as an argument.
The Jist of it is - everything in Java is passed by reference, unless it is a primitive.

Is there an object in Collection isn't static?

I've searched but I did not find a good answer.
I've used an ArrayList object.I created an instance object, (example object X), I used that ArrayList as a parameter on constructor object X, but everytime I created an instance of object X, the ArrayList included the old values, didn't create a new ArrayList.
I need to use add method like arraylist. This is the code:
public DataPacket(int hop, int TTL, ArrayList onetimevisit){
this.hop = hop;
this.TTL = TTL;
this.visited = onetimevisit;
}
in other looping process, DataPacket will meet object NodeRandom:
public NodeRandom(int id){
this.id = id;
}
then DataPacket will add the id of NodeRandom.
Is there an Object in Collection isn't static?
I'll take a guess that your issue has to do with an incorrect assumption about how java passes objects as parameters in method calls. Check out this answer: Is Java "pass-by-reference" or "pass-by-value"?
Short answer:
change
this.visited = onetimevisit;
to
this.visited = new ArrayList (onetimevisit);
Longer answer:
ArrayLists are not necessarily static. I think you're incorrectly inferring that the ArrayList must somehow have been set to static from the fact that there is only one copy of the ArrayList when you pass it in the way you've passed it. The thing to understand is that when you pass an object in Java (an ArrayList, for example), you're passing a reference to the object. A reference is something akin to a C-style pointer with the distinction that pointer arithmetic and such is not allowed. When you call a method and pass an object, the called method just gets a copy of the reference and not a copy of the object. Likewise, when you use the = operator to assign one object to another, you're only assigning the references to equal each other, and there is still only one copy of the object. In your code, both this.visited and onetimevisit are references that come to point to the same object in memory.
On the other hand, ArrayList has something that is somewhat akin to a copy constructor. This constructor, called in my sample code above, creates a shallow copy of the given ArrayList, which seems to be what you want. It is worth noting that an ArrayList does not copy the objects added to it (it stores references to them), so perhaps what you really need is to create copies of the objects as well. This would be done by calling their copy constructors (if they allow copying by providing such a constructor) before inserting them into the ArrayList.
If you want a new ArrayList() you have to create one, it won't do it automagically.

If I return a List in Java, is the return value a reference or the actual value?

Pretty self explanatory: I need to modify the ArrayList that I receive, but I want the original to be unchanged.
I know this is very basic, and I'm not sure why I don't know the definitive answer. I guess better late than never though.
You will have a reference to the original ArrayList.
You can create a shallow copy of the list with clone().
Have a look at this question if you want a deep copy.
Everything in java will be a reference by default. So yes changing the returned arraylist will modify the original one.
To prevent that problem you have to create a copy of the original one. Use the .clone() method for that.
If you want a modified list, but not to modify the original, you shouldn't operate on the list which you received in arguments of the method because you operate on reference. Better use something like this:
public void modifyList(List myList) {
myList.add("aaa"); // original *will* be modified
List modifiable = new ArrayList(myList);
modifiable.add("bbb"); // original will *not* be modified - only the copy
}
It will be the same ArrayList. If you want a copy, you'll have to copy it yourself. Not necessarily easy if the ArrayList holds complex objects!
I think java is pass-by-value always.
The only thing to remember is that objects are passed by passing the value of their address, or reference to them, this makes it seem as if they are passed by reference in C++ terms. Because essentially, you are passing the reference address not a copy of the object. The address is passed by value.
Thus, Java can say it is always passed by value because even when it is passing an object, it is only passing the value of its memory reference on the heap stack, not a clone/copy of the target object.
An Arraylist is an object, therefore it will be passed by value, so the value passed in will be a reference to the original Arraylist on the heap. Any modification to the Arraylist in your function, will modify the original on the heap.
I have not used the .clone(). I leave that to others to help with. Meanwhile, I will go learn about them myself.

Categories

Resources