Copying data into a reference in java (lack of pointer problem) - java

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.

Related

JAVA gui: array being modified unexpectedly

Problem with gui application where array of objects been passed to the constructor, however when new round is initialised, it modifies somehow const_AnimalFamily array, where I want to make it unchanged at each round, however final cannot be used here. Other class initialises this class, however here is my main. Any suggestions? Thank you!
why its been changed each time I modify animalFamily, const_AnimalFamily being affected even if I did not do anything to it?
Your code is much too large for being analyzed. But as you declared two arrays assigning their references to fields, I simply assume that you once assign one field to the other.
And indeed you have the line:
animalFamily = const_AnimalFamily;
I futher assume that you want to copy all contents from const_AnimalFamily to animalFamily. But this is not the case.
In Java, such assignments simply assign the reference to the variable (or the field). That means, both fields now refer to the same array. Actually, the array that was referred to by the field const_AnimalFamily before, is now obsolete and cannot be used anymore.
If you now access some array content, for example
animalFamily[0] = ...
and afterards read from
... = const_AnimalFamily[0]
you will get the same object that you previously wrote into the array.
Solution: If you really wanted to copy the array, do the following:
animalFamily = Arrays.copyOf(const_AnimalFamily, const_AnimalFamily.length);
Another (better) solution would be to use collections.
It's right as per your observation "Problem with gui application where array of objects been passed to the constructor, however when new round is initialised, it modifies somehow const_AnimalFamily array, where I want to make it unchanged at each round".
See this your code:
public AnimalGUI(Animal[] temp) {
System.out.println("INSIDE CONSTRUCTOR");
const_AnimalFamily = temp;
You are changing the reference of const_AnimalFamily to temp. So now whenever you modify temp (from wherever it was passed) you are going to go through same changes in your constant array.
I would suggest you do something like:
You do a deep copy of your temp array rather than changing the reference.
OR
when you pass temp array, you pass the cloned (Arrays.copyOf) version of array rather than raw array.

passing an ArrayList to a function makes changes in the original ArrayList

I need to pass the same ArrayList from the main function to 3 different functions (all in different classes).
When the 1st function receives the ArrayList, it makes changes not only in the local copy of the list but also the original ArrayList in the main method gets modified. This indicates that the changes are being made at the memory address.
So, in the first function I copied the received arraylist into another arraylist of the same type, using:
for(int i=0;i<valuex.size();i++)
{
temp1=valuex.get(i);
VALUE.add(temp1);
}
This worked for the first time when I introduced this modification but then the same problem restored. Later I made three copies of the arraylist and passed each copy to each of the 3 functions. This too failed.
I didn't use
clone();
because this created the same problem some time back..
Please help...
You have described a shallow copy - you've made a fresh list, but you've got the same objects in each list.
If this isn't working for you, it suggests your method is modifying the list objects. To avoid this being a problem, you'll have to perform a deep copy - creating copies of each of your objects.
For example:
List<Foo> oldList = // ...
List<Foo> newList = new ArrayList<>();
for (Foo foo : oldList) {
Foo newFoo = new Foo(foo); // copy constructor
newList.add(newFoo);
}
When you passed a copy of the list to your three methods, you passed a reference to a copy of the list as a data structure. However, both lists, in memory, ended up pointing to the very same objects.
If your methods are changing the actual objects that the lists are pointing to, and you'd like to avoid that, then cloning the list is not enough: you must clone each and every object in the list as well.
By the way: the reason that clone() didn't work for you is that clone() only performs a shallow clone of the list: it creates a brand new ArrayList instance in memory, however the list's constituents are still the same objects (in memory) as the objects pointed-to by the original list.
You can just create a new ArrayList based on your existing arrayList before passing it in as argument.
List existingList = new ArrayList();
o1.m1(new ArrayList(existingList));
o2.m2(new ArrayList(existingList));
o3.m3(new ArrayList(existingList));
ArrayList contructor allows you to create a new ArrayList based on an existing collection.
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#ArrayList(java.util.Collection)

Should I have two different variables in one class that represent almost the same thing

At first I had a class A that took a list B as constructor argument. This list B was kept within class A in a variable. Another class that used this class A needed the data in list B, but in a different way. So I created a specific object C and had a getSomething() method in class A that on the fly created one of these object C, based on information in the original list B. This worked fine.
Then it turned out that the class that called getSomething() needed a little bit extra information that the original list B did not contain. A small calculation on the specific elements in list B however gave me that information. That information needed to be added to the object C. This calculation is a bit heavy so I do not want to do it on the fly when I create object C in getSomething(). This gave me a problem since I cannot update any elements of object C with this calculated information, since the elements of object C do not exist yet, they are created in getSomething().
How should I solve this the best way. Are there perhaps any patterns?
Do I in the constructor of class A convert the elements in list B to a list of object C and then discard list B, and then perform the calculation and updates all elements of object C?
Do I keep both the original list B and a list of object C and have two variables with almost the same information, just presented in a different way?
Or something else?
Edit: C is not an extension of an element in list B, its more that one or more elements in list B is combined to a C.
If you can make adjustments to list B to create list C without losing information that class A needs (in other words if class A can function just fine with only list C) then yes, calculating this in the constructor and not keeping B seems like a good idea.
If, however, you need the original data aswell, class A can keep both. In case you know which information will be the same in list B and list C, you can give the instance of list C a reference to list B, so that it only has to store the information that differs, and can refer to the information in list B when requested something that didn't change.
The explanation is probably more confusing than the actual problem.
AFAICT you want a decorated B, where the decorated list is computed at in A's constructor.
Whether or not it's copies of B's objects, or a composited reference to the originals (or something else) depends on your actual needs.

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.

regarding object recycling

I have a question. What is wrong with regards to the below code:
ArrayList tempList2 = new ArrayList();
tempList2 = getXYZ(tempList1, tempList2);
//method getXYZ
getXYZ(ArrayList tempList1, ArrayList tempList2) {
//does some logic and adds objects into tempList2
return tempList2;
}
The code will get executed but it seems by passing tempList2 to the getXYZ method argument, it is doing object recycling.
My question is, Is recycling the tempList2 arraylist object correct?
My question is, Is recycling the tempList2 arraylist object correct?
I don't quite know what you mean by "recycling". This doesn't appear to be a case where the application is recycling objects in an attempt to avoid allocating new objects. (That is the normal meaning of "recycling" in Java.)
If getXYZ is called multiple times with the same tempList2 object, then this is simply a way of aggregating stuff into a single list. The fact that getXYZ returns an ArrayList leaves open the possibility that the method implementation may be changed to return a different ArrayList instance. That's not a problem per se, but it might be if the caller doesn't assign the result of the call appropriately.
If getXYZ is only called once for any given tempList2 object, then this looks a bit strange.
In summary, this code looks a bit fishy, and is fragile if someone changes the implementation of getXYZ. However, it is not down-right wrong, and there may be some good reason (or historical reason) for doing things this way that is not apparent in the small chunks of code you included in the question.
EDIT - in response to this comment (inlined to make it readable)
Actually, the reason for the above code is, I wanted to avoid creating two arraylist objects. For ex: the conventional method would be
ArrayList tempList2 = new ArrayList();
tempList2 = getXYZ(tempList1);
//method getXYZ
getXYZ(ArrayList tempList1) {
ArrayList tempList = new ArrayList();
//INSTANTIATED ONLY ONCE
//does some logic and adds objects into tempList
return tempList;
}
The real conventional way of doing this would be:
ArrayList tempList2 = getXYZ(tempList1);
or
ArrayList tempList2;
// some intermediate lines
tempList2 = getXYZ(tempList1);
Neither of these require creating the unnecessary ArrayList instance of your approach, and neither require passing 2 ArrayList instances into the getXYZ method.
There's really no such concept as "object recycling" here. Nothing's being garbage collected, if that's what you're interested in... at least, not if there are no lines like this:
tempList2 = new ArrayList();
within getXYZ().
The reference to the ArrayList is passed into the method and then returned. That's all. It's just a reference - it's not the object itself.
Now you could say it's slightly odd for the method to return the ArrayList reference which was passed into it... usually that's used for fluent interfaces, but it doesn't seem to be the case here.
You're passing the value of the tempList2 reference. The object itself isn't copied. So when the passed-in tempList2 is modified, the caller sees the changes. This is also called call-by-sharing
So there's nothing wrong, once you understand what's going on.

Categories

Resources