When list.addAll(list2) is called will objects in lists be copied to list? or just copy their references... did not find any explanation on javadoc...
No copy of the objects or their data are made; their references are simply added to the list object.
No, the objects will not be copied; references to the same objects will be added to the list.
In general, java will not copy objects when you "add all", that is, for objects, pointers to the originals are used.
* But be careful ! For strings, due to immutability, an array copy will not point to the original string values, and you must not expect that changing a pointer to a string that was added to an array list will result in a new value inside the array list.
Related
I'm working on some code and trying to figure out how to copy an object reference to another object. I keep seeing the clone() method used, but I've read it's flawed and the class I'm wanting to copy is already implementing serializable. So one question I have is about the difference between using '=' and the clone method - My understanding is that both of these are shallow copies so they should work the same, but if that's true, then what is the benefit of having a method for this?
The code I'm working on has 2 arrays of objects - both the same type of object, all objects in both arrays are initially null, and I assign the values of array B to equal array A.
As the code progresses objects in array A are initialized and values are assigned to the variables of the objects in array A.
At the end of the code though, all objects in array B are still null.
Do I have the concept wrong here?
If the concept isn't wrong I assume it's just something I'm overlooking in my code.
Any help is appreciated.
I'll make my comment an answer:
Your question is comparing apples to oranges, they are so completely different that they can't be compared. = assigns a reference, that's it. Clone creates a completely new object, one whose state should be the same as the cloned object, but again it is a completely different object/reference. As an aside, there are deep and shallow clones, and so the composite fields of shallow copied clones may be identical, but that's the subject of another question.
When you use =, you copy the reference of the object (in memory). When using .clone(), you create a new object.
I have encountered a problem in one of my Java projects, which causes bugs.
The problem sounds as following:
I have two arrays. Let's name them firstArray and secondArray. Object in this case is a seperate class created by me. It works, the array can be filled with objects of that type.
Object[] firstArray= new Object[];
Object[] secondArray = new Object[];
Now, when I get an element out of the first array, edit it and then copy it in the second array, the object from the first array gets altered too.
tempObj = firstArray[3];
tempObj.modifySomething();
secondArray[3] = tempObj;
Whenever I do this, the (in this case) 3rd element(actually 4th) of the first array gets the modifications. I don't want this. I want the first Array to remain intact, unmodified, and the objects I have extracted from the first array and then modified should be stored in the second so that the second array is actually the first array after some code has been run.
P.S. Even if I get the element from the first array with Array.get(Array, index) and then modify it, the element still gets modified in the first array.
Hopefully you understood what I wanted to say, and if so, please lend me a hand :)
Thank you!
You're going to have to create a new object.
The problem is the modifySomething call. When you do that, it alters the object on which it's called. So if you've only got one object (even by two names), you can't call modifySomething or they will both change.
When you say secondArray[3] = firstArray[3], you aren't creating a new object: you're just assigning a reference. Going through an intermediate temporary reference doesn't change that.
You'll need code that looks like this:
Object tempObj = firstArray[3].clone();
tempObj.modifySomething();
secondArray[3] = tempObj;
The clone() method must return a new object divorced from the original but having identical properties.
When you retrieve an element from your array, you have a reference to it. So if you modify it, the modification are shered through all the object's references.
In order to leave it intact, you should use some method like Object.clone() or create a new Object and use its constructor to initialize its fields.
The object extracted from the first array needs to be cloned to create a new instance that is seperate. Otherwise the modification will affect the object in the first array as it is the same object.
When you retrieve an element from your array, you get a reference to it. So if you modify it, the modification are shared through all the object's references.
In order to leave it intact, you should use some method like Object.clone() or create a new method which take in input your retrieved object and return a new one alike.
In Java, when you do this secondArray[3] = tempObj;, you actually put the reference to the array, not the real object
So firstArray[3] and secondArray[3] point to the same real object
What you need to do is to create a new object that is identical to your original object, and put the reference of the new object to your secondArray
It might worth to point out that default clone() function only does a shallow copy, so if you have mutable objects in your object's fields, it might cause some problems. Take a look at this article about how to do a deep copy
Need some inputs:
Lets say i have N ArrayList and in each i am adding foo() object.
Foo foo = new Foo()
A.add(foo);
B.add(foo);
N.add(foo);
Now modification done on any one foo() object will reflect in all the other arraylist?
If YES WHY? and
whether this behaviour can also be achieved using any other collection like Vector etc...?
IF i make foo as null will it reflect in all arraylist?
Yes, because all lists only contain a reference to the same objects
Yes, all collections work like that
No, because you can only set a reference to null, and each list has a copy of the reference.
Any implementation of Collection API such as ArrayList or Vector hold reference to an object in heap memory so when you would get an index of a List by get(index) method, you achive reference to object so:
Yes, if get an index of list by get(index) method and then change the stat of the achieved object, changes stay in memory.
Yes,All Collection API have this behavior.
No,When achieve to a index of list, act is: "You achieve a copy of reference to object" and when set it to null, list instance don't any change.
Just a thought question here. In C++, I could do the following:
vector<vector<string> > data;
// add data into data
//..
data[0].push_back( "somedata" );
And I would expect somedata to get written to the vector array because the [] notation gives me access to the object by reference. What about in Java? If I:
List<List<String>> data = new ArrayList<List<String>>();
// add data into data
//..
data.get(0).add( "somedata" );
Would this actually write somedata into the data object? Or would it create a new copy of the element at data(0), add somedata to that, and then that object disappears into GC sometime down the line?
ArrayList is a List backed-up by array (in order to enable random access) the list stores references to real elements so when you add a new element as you mentioned, the reference to it will be added to the ArrayList (and the backing Array will point to this List element).
You must first understand that List, String, etc. in Java, these types are reference types. Their values are references, which are pointers to objects. Thus, List<List<String>> in Java would be most equivalent to vector<vector<string *> *> * in C++. You cannot have a direct "object value" in Java like you can in C++; objects are always hidden behind a pointer.
So to answer your question, yes, the Java code you show works, but for very different reasons. In your Java code, you have a list of references (pointers). You want to modify stuff in the object that is pointed to by one of these pointers, but you do not need to change the pointer itself. Thus, there is no need to return the element by reference. It is sufficient to return the element (a pointer) by value.
Your question "Would this actually write somedata into the data object?" is kind of ambiguous. The code modifies the object pointed to by the first element of the list. Whether this constitutes modifying the list object itself depends on what you consider to be "part of" an object. As explained earlier, the list object contains a collection of pointers to objects. Should the objects pointed to by these pointers to be considered "part of" the list object? There could be many pointers to the same object. So if you consider it to be a part of the container, then what happens when there are pointers to the same object in multiple containers, is the object then part of all of these containers at the same time?
The answer to "Or would it create a new copy of the element at data(0)" is, it creates a copy of the pointer that is the first element. It does not create a copy of the object that the pointer points to.
Almost. The pattern you need is:
List<List<String>> data = new ArrayList<List<String>>();
data.add(new List<String>());
data.get(0).add( "somedata" );
The first line creates only the "outer" List of Lists; you have to populate it with one or more Lists (of Strings) before you can add data to the inner lists.
In Java, we can always use an array to store object reference. Then we have an ArrayList or HashTable which is automatically expandable to store objects. But does anyone know a native way to have an auto-expandable array of object references?
Edit: What I mean is I want to know if the Java API has some class with the ability to store references to objects (but not storing the actual object like XXXList or HashTable do) AND the ability of auto-expansion.
Java arrays are, by their definition, fixed size. If you need auto-growth, you use XXXList classes.
EDIT - question has been clarified a bit
When I was first starting to learn Java (coming from a C and C++ background), this was probably one of the first things that tripped me up. Hopefully I can shed some light.
Unlike C++, Object arrays in Java do not store objects. They store object references.
In C++, if you declared something similar to:
String myStrings[10];
You would get 10 String objects. At this point, it would be perfectly legal to do something like println(myStrings[5].length); - you'd get '0' - the default constructor for String creates an empty string with length 0.
In Java, when you construct a new array, you get an empty container that can hold 10 String references. So the call:
String[] myStrings = new String[10];
println(myStringsp[5].length);
would throw a null pointer exception, because you haven't actually placed a String reference into the array yet.
If you are coming from a C++ background, think of new String[10] as being equivalent to new (String *)[10] from C++.
So, with that in mind, it should be fairly clear why ArrayList is the solution for an auto expanding array of objects (and in fact, ArrayList is implemented using simple arrays, with a growth algorithm built in that allocates new expanded arrays as needed and copies the content from the old to the new).
In practice, there are actually relatively few situations where we use arrays. If you are writing a container (something akin to ArrayList, or a BTree), then they are useful, or if you are doing a lot of low level byte manipulation - but at the level that most development occurs, using one of the Collections classes is by far the preferred technique.
All the classes implementing Collection are expandable and store only references: you don't store objects, you create them in some data space and only manipulate references to them, until they go out of scope without reference on them.
You can put a reference to an object in two or more Collections. That's how you can have sorted hash tables and such...
What do you mean by "native" way? If you want an expandable list f objects then you can use the ArrayList. With List collections you have the get(index) method that allows you to access objects in the list by index which gives you similar functionality to an array. Internally the ArrayList is implemented with an array and the ArrayList handles expanding it automatically for you.
Straight from the Array Java Tutorials on the sun webpage:
-> An array is a container object that holds a fixed number of values of a single type.
Because the size of the array is declared when it is created, there is actually no way to expand it afterwards. The whole purpose of declaring an array of a certain size is to only allocate as much memory as will likely be used when the program is executed. What you could do is declare a second array that is a function based on the size of the original, copy all of the original elements into it, and then add the necessary new elements (although this isn't very 'automatic' :) ). Otherwise, as you and a few others have mentioned, the List Collections is the most efficient way to go.
In Java, all object variables are references. So
Foo myFoo = new Foo();
Foo anotherFoo = myFoo;
means that both variables are referring to the same object, not to two separate copies. Likewise, when you put an object in a Collection, you are only storing a reference to the object. Therefore using ArrayList or similar is the correct way to have an automatically expanding piece of storage.
There's no first-class language construct that does that that I'm aware of, if that's what you're looking for.
It's not very efficient, but if you're just appending to an array, you can use Apache Commons ArrayUtils.add(). It returns a copy of the original array with the additional element in it.
if you can write your code in javascript, yes, you can do that. javascript arrays are sparse arrays. it will expand whichever way you want.
you can write
a[0] = 4;
a[1000] = 434;
a[888] = "a string";