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.
Related
With 2 ArrayList, I was wondering if the best way from transforming the 1st one into a "copy" of the second one is to go like
myFirstArray.clear();
myFirstArray.addAll(mySecondArray);
or
myFirstArray = mySecondArray.clone();
What are the main differences between those two method, which on is preferrable and is there another "easier" or "cleaner" solution. Thanks for any tips
EDIT : I use this copy for replacing an Array of item im currently working with the one where I store the item I'll work with in the next loop. At the end of the loop I replace my currentArrayList with my futurArrayList and I clear my futurArraylist in order to add new item in it (i hope its clear enough)
The first one replaces the content of the list by another content. The second one creates another ArrayList instance, leaving the previous one untouched.
If the list is referenced by some other object, and you want this other object to be untouched, use the second one. If you want the other object to also have the new content, use the first one.
If nothing else referenced the list, it doesn't matter much. The second one will reduce the memory used in case you replace the content of a huge list by a few elements.
In java, though clone is ‘intended’ to produce a copy of the same object it is not guaranteed.
Clone comes with lots of its and buts. So my first advice is to not depend on clones.
By default, java cloning is ‘field by field copy’ i.e. as the Object class does not have idea about the structure of class on which clone() method will be invoked. So, JVM when called for cloning, do following things:
If the class has only primitive data type members then a completely
new copy of the object will be created and the reference to the new
object copy will be returned.
If the class contains members of any class type then only the object
references to those members are copied and hence the member
references in both the original object as well as the cloned object
refer to the same object because of that cloned object changes are visible in original also.
Use that:
List<Object> first = ...
ArrayList<Object> second = new ArrayList<>(first);
I also suggest that you do not use clone() at all. It's better to use a copy constructor or some factory method. Take a look at here.
Of course in your case, with the ArrayList, it will work as expected, you will end up with a copy of the references.
Guava, guava, guava!
final List copied = ImmutableList.copyOf(originalList);
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.
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.
I got some problem with reference assignment in java.
Let me explain: in my code, i'm using an ArrayList of BooleanWrap (a home made class of boolean) which will be later assigned as a value in a HashMap (there is a for cycle which update the values of this ArrayList until a condition is verified).
Something like this:
ArrayList<BooleanWrap> temp=new ArrayList <BooleanWrap>(48);
//cycle: operations to fill the ArrayList, then a condition is satisfied
hashMap.put(index, temp);
After that, I have to reuse the temp variable, so I need to reinitialize it. I do it with the following instructions:
for(BooleanWrap bool: temp){
bool.set(false);
}
There comes my problem: assigning temp as a value of the hashMap will save only the reference of the variable, not the actual value.
So, reinitializing temp cause also the updating inside the hashmap (in this case, setting everything false).
Now, I think that even with clone() method I should get the same result (cause it produces a shallow copy of the ArrayList).
Is there a way to reuse the same variable temp in my cycle without assign later the reference of it to the hashmap?
Actually I can do it with a method which creates a deep copy of the arraylist:
public static ArrayList<BooleanWrap> deepcopy(ArrayList<BooleanWrap> original){
ArrayList<BooleanWrap> copy=new ArrayList<BooleanWrap>(48);
for(BooleanWrap bool: original)
copy.add(new BooleanWrap (bool.get()));
return copy;
}
but I need something done inline, without any other methods and as shorter as it can be.
Any advice/suggestion/insult?
The issue is not about variables. It is about objects and mutations upon them.
So create a new object as needed. The "issue" is that the original object stored in the HashMap is being mutated.
Avoiding re-use of variables, however, can (often does?) make code much more maintainable and understandable.
Happy coding.
After that, I have to reuse the temp variable, so I need to
reinitialize it. I do it with the following instructions:
for(BooleanWrap bool: temp)
{ bool.set(false); }
That does not re-initialize the temp variable. That re-initializes the contents of your temp variable. to re-initialize the temp variable your code would look like
ArrayList<BooleanWrap> temp=new ArrayList <BooleanWrap>(48);
//cycle: operations to fill the ArrayList, then a condition is satisfied
hashMap.put(index, temp);
//After that, I have to reuse the temp variable, so I need to reinitialize it.
// I do it with the following instructions:
temp = new ArrayList <BooleanWrap>(48);
//cycle: operations to fill the ArrayList
Using a BooleanWRap is very inefficient, even a Boolean would be inefficient.
Instead I suggest you use a BitSet.
BitSet temp = new BitSet(48);
//cycle: operations to fill the ArrayList, then a condition is satisfied
hashMap.put(index, temp);
// to create a new BitSet...
temp = new BitSet(48);
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.