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.
Related
I have an issues for pass by value in HashSet. Every time i would like to copy data from inside the table and paste the data on other page. But the problem i facing was it end up with pass by reference instead on pass by value. Which mean when i click 'Paste' button the data is the new 1 instead on old 1 that suppose saved in my hashset. Please advice how should i resolve this issues Thank you very much.Below is my code:
static HashSet<ScmTelephoneDetailsViewRowImpl> copy_set = new HashSet<ScmTelephoneDetailsViewRowImpl>();
public void copy_data(ActionEvent actionEvent){
for(int z=0;z<scm_details_row.getRowCount();z++){
ScmTelephoneDetailsViewRowImpl telephone_accounting_details_9 =(ScmTelephoneDetailsViewRowImpl)scm_details_row.getRowAtRangeIndex(z);
copy_set.add(telephone_accounting_details_9);
}
System.out.println("copy_set " + copy_set.size());
System.out.println("copy_set " + copy_set.getClass());
}
public void paste_data(ActionEvent actionEvent){
System.out.println("Paste Data");
Iterator setIterator =copy_set.iterator();
while(setIterator.hasNext()){
ScmTelephoneDetailsViewRowImpl get_interator = (ScmTelephoneDetailsViewRowImpl)setIterator.next();
//System.out.println("copy_set "+ setIterator.next());
System.out.println("data inside "+ get_interator.getTelephoneUser());
}
}
In Java there is no way to pass by-reference types by value: you can do that only with primitive types and references themselves. When you want a copy semantic, you need to implement it yourself.
What's happening in your code is that you are making a shallow copy of your set:
for(int z=0;z<scm_details_row.getRowCount();z++){
ScmTelephoneDetailsViewRowImpl telephone_accounting_details_9 =(ScmTelephoneDetailsViewRowImpl)scm_details_row.getRowAtRangeIndex(z);
copy_set.add(telephone_accounting_details_9);
}
The loop above makes you a new collection, in the sense that if you add or remove anything from copy_set, the original scm_details_row is not going to see the difference. However, if you change any of your ScmTelephoneDetailsViewRowImpl objects, the objects in the original collection will change as well, because that's the same object.
To work around this problem, make a copy constructor or implement some sort of a "cloning" method for "deep" copying, and insert deep copies into the copy_set:
for(int z=0;z<scm_details_row.getRowCount();z++){
ScmTelephoneDetailsViewRowImpl telephone_accounting_details_9 =
(ScmTelephoneDetailsViewRowImpl)scm_details_row.getRowAtRangeIndex(z);
ScmTelephoneDetailsViewRowImpl copyRow =
new ScmTelephoneDetailsViewRowImpl(telephone_accounting_details_9);
copy_set.add(copyRow);
}
In order for this to work you need to define a "copy constructor" for your ScmTelephoneDetailsViewRowImpl class:
public ScmTelephoneDetailsViewRowImpl(ScmTelephoneDetailsViewRowImpl other) {
// Initialize this object using the data from the object "other" passed as the parameter
this.someFieldOne = other.someFieldOne;
this.someFieldTwo = other.someFieldTwo;
// If there are collections in the object, make deep copies of them as well
...
}
Clearly ScmTelephoneDetailsViewRowImpl is an object, and not a simple value. But what I think you want is a new object, that is identical to the original object (all the fields are the same) but which occupies different memory.
Have you tied something like
ScmTelephoneDetailsViewRowImpl temp = telphone_accounting_details_9.clone();
copy_set.add(temp);
What you really want here is a deep copy. which copies all the fields manually.
If your class ScmTelephoneDetailsViewRow is something you can extend or modify directly, then you could override the clone() function that inherits from Object.
REVISION: in order to call clone() on your object it will need to implement the "interface" called Cloneable. But there are no methods in that interface. So you just need to add "implements Cloneable" to the class definition. Assuming you control that class.
Another problem with the default implementation of clone() is that if your object contains any non-primitive fields, such as an array, than a copy of the pointer to the array will be made, it will not create a "deep" copy where it generates new array space and copies all the array elements too. As I said earlier, you can overcome that if you #Override clone(), or make a new copy command of your own choosing.
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.
I have deep nested structures, and methods like "remove(<Something>)", "contains(<Something>)" etc. rely on access to the original reference in order to remove it etc. (a copy of the reference won't do).
How have people best worked around this so they can still conveniently add, remove, test for etc. the object they want, within different arbitrary methods and constructors etc., without adding any unnecessary complexity or any unnecessary loss in performance?
Methods like remove and contains work fine with pass by value. The reason is that the even though the references are copied, they copy has the same value of the original. Just look at the Collections API. If you do something like (psuedocode)
List list = new List();
list.add(object1) // assume you have an object1 reference
and then you do
myRemove(list, object1);
both list and object 1 are passed by value, so in the myRemove method they are copies of the original reference. If in myRemove you do
list.remove(object1);
the object is still removed from the list no problem. Furthermore, since the list and object1 references in both scopes point to the same underlying objects, the list reference in the calling scope refers to the list that has the object removed.
The only time you would need pass by reference semantics is if you want to modify a reference in a method and have the modification apply in the scope that called the method.
So if you want to do
List myList = new List();
changeList(myList);
and have changeList change where myList points in the calling scope, it wont work without some trickery. The trickery is called double indirection. Basically, you create an object that has an instance of what you want to be able to access with pass by reference semantics, and you pass the container object around.
So
class MyContainer {
List list
}
now you can pass an instance of MyContainer into a method, and change the list value, and in the calling scope where the list points will be changed. Note that you are not doing anything special here, everything is still pass by value.
How have people best worked around this so...
By use of member fields (for working with references, not copies) and by use of inheritance and interfaces (for handling nested structures).
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.
So I have an ArrayList in java. And what I'm doing is creating a new list with updated values. But I want to put those new values into the original ArrayList. This is important because I'm passing the original arraylist reference to an object that I no longer have access to, but I need to keep its contents up to date. Is there any way to make java copy the contents into a current reference? I hope that makes sense.
Also, I'd rather not clear the original arraylist and then loop through it pushing the new contents into it.
I need to do something like this:
ArrayList a;
ArrayList *b = a;
//pass b (the pointer) to something
ArrayList c;
*b = c;
I really hope I got that (pseudo) c++ code correct or I'll look pretty stupid =P
I can see how I'm not being clear, it's kind of complicated (this is in android so it's across a couple activities) so let me see if I can get my point across better.
Class1{
ArrayList a;
method1(){
a = Class2.getA();
method_that_uses_a(a);
}
}
Class2{
ArrayList getA(){
ArrayList a = new ArrayList
a = getDataFromWebsite();
return a;
}
Class1's method1() gets called periodically by another portion of code. But I need the reference to a stay the same, but the contents to change to the new contents.
I think your question is unclear, what do you mean by
"And what I'm doing is creating a new list with updated values. But I want to put those new values into the original ArrayList. This is important because I'm passing the original arraylist reference to an object that I no longer have access to, but I need to keep its contents up to date. Is there any way to make java copy the contents into a current reference? I hope that makes sense."
When you do
List a = new ArrayList
List b = a
you have one ArrayList object, and two references to the object, a and b.
Also note that there is an addAll method that you can use to add members of one collection to another collection. Note that I believe addAll does not do a deep copy, so if you use it both lists have copies of the same reference. So if list a has references a1, a2, a3, and you do b.addAll(a), b now has references to the objects that a1...a3 point to...
The array classes all expose public clone() methods, however, so if a
shallow copy of the array is sufficient then
return (ElementType[]) myArray.clone();
Makes for a nice, simple, easy to read paradigm. If "ElementType" is a
primitive type then there is no distinction between shallow and deep
copying, and if it is immutable then performing a deep copy would be
wasteful. In some other circumstances a shallow copy is what you would
want anyway (you want the receiver to be able to mutate the returned
array elements with effects visible to the host object).
If you find that you really do want to make a deep copy of the array
then you might want to consider whether your design can be improved; it
is not necessarily so, but I wouldn't be surprised.
In Java as I hope you;ve found out by now, all variables are references. Among other things this means that unless they are assigned to an object they don't 'point' at anything. You need to write:
ArrayList a = new ArrayList();
or a doesn't 'point to' an actual object - it's just null.
If you write:
ArrayList a = new ArrayList();
ArrayList b = a;
modify(b);
ArrayList c = b;
then there is only one ArrayList. All the variables a, b and c refer to it. Any modifications done in the 'modify' method apply to it, and will be reflect in the state of a, b and c.
You're C++ code says this:
ArrayList a; //make arraylist
ArrayList *b = a; //set b to point to same arraylist as a
//pass b somewhere
ArrayList c; //make arraylist
*b = c; //variable b in THIS PROGRAM now points to c. arraylist is unchanged.
You want to update the arraylist, not the pointer to it, as that pointer only 'exists' in the current context. The code you passed the arraylist to doesn't give a darn if a pointer back in who-knows-where now points to the same arraylist that its using. It's the actual object the other code cares about. To update that object, you can just call methods on it, like a.add(bar)
BUT there's more to it. If you call a function you don't control (now known as foo) and pass it an arraylist, that's all fine. But if you want to update it from the code calling foo, you run into issues. Imagine if an object you were working with could change randomly at any time. All sorts of bad stuff could happen. If you really need this capability (and we can help you judge if you do), look into the topic of threading.