I want to make a deep copy of an object array using a constructor.
public class PositionList {
private Position[] data = new Position[0];
public PositionList(PositionList other, boolean deepCopy) {
if (deepCopy){
size=other.getSize();
data=new Position[other.data.length];
for (int i=0;i<data.length;i++){
data[i]=other.data[i];
}
However, what I have above for some reason is not working. I have automated tests that I run, and its failing those tests. So theres an error an here that Im not sure what it is.
What you have implemented is a shallow copy. To implement a deep copy, you must
change
data[i] = other.data[i];
to some thing that assigns a copy of other.data[i] to data[i]. How you do this depends on the Position class. Possible alternatives are:
a copy constructor:
data[i] = new Position(other.data[i]);
a factory method:
data[i] = createPosition(other.data[i]);
clone:
data[i] = (Position) other.data[i].clone();
Notes:
The above assume that the copy constructor, factory method and clone method respectively implement the "right" kind of copying, depending on the Position class; see below.
The clone approach will only work if Position explicitly supports it, and this is generally regarded as an inferior solution. Besides, you need to be aware that the native implementation of clone (i.e. the Object.clone() method) does a shallow copy1.
In fact the general problem of implementing deep copying in Java is complicated. In the case of the Position class, one would assume that the attributes are all primitive types (e.g. ints or doubles), and therefore a deep versus shallow copying is moot. But if there are reference attributes, then you have to rely on the copy constructor / factory method / clone method to do the kind of copying that you require. In each case it needs to be programmed in. And in the general case (where you have to deal with cycles) it is difficult and requires each class to implement special methods.
There is one other potential way to copy an array of objects. If the objects in the array are serializable, then you can copy them by using ObjectOutputStream and ObjectInputStream serialize and then deserialize the array. However:
this is expensive,
it only works if the objects are (transitively) serializable, and
the values of any transient fields won't be copied.
Copying by serialization is not recommended. It would be better to support cloning or some other method.
All in all, deep copying is best avoided in Java.
Finally, to answer your question about the Position classes copy constructor works, I expect it is something like this:
public class Position {
private int x;
private int y;
...
public Position(Position other) {
this.x = other.x;
this.y = other.y;
}
...
}
As #Turtle says, there's no magic involved. You implement a constructor (by hand) that initializes its state by copying from an existing instance.
1 - It is specified that the Object implementation of clone() does a shallow copy, but this may be overridden. The javadoc for clone specifies the "contract" as follows:
"Creates and returns a copy of this object. The precise meaning of "copy" may depend on the class of the object. The general intent is that, for any object x, the expression: x.clone() != x will be true, and that the expression: x.clone().getClass() == x.getClass() will be true, but these are not absolute requirements. While it is typically the case that: x.clone().equals(x) will be true, this is not an absolute requirement."
Nothing in the "contract" talks about deep versus shallow copying. So if you are going to use clone in this context, you need to know how the actual classes clone method behaves.
When you say:
data[i]=other.data[i];
You are just copying a list of references (assuming this is an array of objects). If you want to make a deep copy, you need to use new to create a new instance of each object in the array.
Instead of saying:
data[i]=other.data[i]
You will want to make a copy constructor for Position (in other words, a constructor for Position that takes in another Position and copies the primitive data inside it) and say data[i]=new Position(other.data[i]);
Basically your "deep copy" constructor the PositionList is a copy constructor, although copy constructor does tend to indicate a deep copy, so the deepCopy parameter is unnecessary.
Here is a function I use:
function copy(arr) {
return arr
.map(x => Object
.keys(x)
.reduce((acc, y) => {
acc[y] = x[y]
return acc
}, {}))
}
It only works on arrays with objects with a single level.
This should make a "deep" copy
int [] numbers = { 2, 3, 4, 5};
int [] numbersClone = (int[])numbers.clone();
Related
I'm having an odd problem that I haven't encountered before with copying objects in Java.
So, I've written a class in my code called "State". This contains a few ints, a 2d array, a string and such...
So, for an instance of State called S, I want to make a copy of it called X (I do this simply by writing State X = S; ). Then I want to make changes to X, do some evaluations based on those changes and then just throw away X and keep using S. However, the problem I'm getting is that S seems to be getting the changes that I make to X.
This seems odd to me, since I feel quite certain that I've done things like this before but never had this problem.
Any thoughts?
(Thanks in advance)
I want to make a copy of it called X (I do this simply by writing State X = S; ).
That does not make a copy of the object.
Variables (of non-primitive types) in Java are references - they are not the objects themselves. By doing
State X = S;
you are not copying an object, you are just copying the reference - the result is that you now have two variables that are referring to the same object. If you modify the object through one reference, you'll see the changes also through the other reference.
One way to copy objects is by using the clone() method. For this to work, the class of the object that you are trying to copy must implement interface Cloneable. Another (and probably better) way is to create a copy constructor, and use it to copy the object:
public class State {
public State(State other) {
// initialize this object by copying content from other
}
}
// Make a copy
State X = new State(S);
Your code is not creating a copy of the object. What you are doing there is creating a new reference and pointing it to the same object.
Search for "how to clone an object in Java". Read up on the Cloneable interface.
I need help with something. my code is of the following template.
Assume customObject has multiple property1, property2, ..property100.
List<CustomObject> customObjectList = /*<method call to external API that returns the said list >*/
if(customObjectList != null && customObjectList.size() > 0){
//*** point A ***<clone the Object>
resultList = <some method that process the above list>(customObjectList)
if(resultList.size() > 0){
for(Iterator<Map.Entry<CustomObject, ExternalResponse>> itr = resultList.entrySet().iterator(); itr.hasNext();) {
//code that modifies the properties in the CustomObjects
//*** point B ***resetAProperty(<Object clone>)
}
}
}
At point B, I need the one unmodified specific property of original object to use in the method. I have two strategies for this:
Clone the object at point A, and use the cloned copy to get the
property as shown in above code. At point A, Use a for loop and a
Map to form an associate array of object names, property original
values and traverse them to get the property initial value at point
B
Avoid Cloning because it always requires Deep Cloning
.clone() especially on a List will almost always end in tears because you would have to deep clone all the objects in the list, all their referenced objects, and so on.
Deep Cloning means you have to make a binary copy of every last object in the Object graph. Just copying a reference will give you a shallow copy and you will see any changes that are made to the referenced object. Just miss one property and you will have a hell of a time finding that bug.
Solution
What you should do is make all your CustomObject instances Immutable and then you don't need to worry about versioning, they can never change, mutation would involve creating a new instance that is also Immutable and a complete different object. Then you never had to worry about versions.
Of course all the instance variables that point to other objects will need to be Immutable as well. This is the same problem as the deep clone but taking from another angle. A much more manageable angle.
I am trying to clone an object of MyGraph and I want it to be a deep copy so the arraylists inside the object are also cloned. Right now I have:
public static MyGraph deepCopy(MyGraph G){
MyGraph Copy = (MyGraph) G.clone();
Copy.VertexG = (ArrayList<Integer>) G.VertexG.clone();
Copy.EdgeG = (ArrayList<String>) G.EdgeG.clone();
return Copy;
}
This returns an error when it tries to clone the arraylist. I am not sure if this is the right way to add the arraylists to the object.
The clone operation in ArrayList returns a shallow copy of the object, and will not be suitable for your purposes. The manual workaround is to:
Create a target array list of the same size as the source list
Iterate the source list and create a clone of each of it's items, into the target list
Obviously, this will only work if the array list contains items that implement clone, and in addition that the items clone operation actually returns a deep copy. In other words, its not guaranteed. Actually, implementing deep clone functionality for Java objects is not at all easy, refer to extensive discussions in Java: recommended solution for deep cloning/copying an instance and other SO threads to get a feel for the options available. In addition to the answers provided there, here are some other options:
Serialization
If all (the required) objects in your hierarchy can be serialized then you can use this simple code to do a deep clone:
public MyGraph deepCopy() {
try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
final ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
oos.close();
final ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(baos.toByteArray()));
final MyGraph clone = (QuicksortTest) ois.readObject();
return clone;
} catch (final Exception e) {
throw new RuntimeException("Cloning failed");
}
}
Note that some deep-clone libraries combine standard Java serialization with reflection hacks and/or byte code instrumentation in order to make the entire object hierarchy fully serializable. You may, or may not, need that.
Copy tools
For example, Dozer, provide fast deep-copy functionality. Orika can also achieve the same, albeit with more configuration:
public MyGraph deepCopy() {
final DozerBeanMapper mapper = new DozerBeanMapper();
final QuicksortTest clone = mapper.map(this, MyGraph.class);
return clone;
}
The only downside of course, being the additional dependencies you need to pull into your project.
On a total tangent, your deepCopy method should not be static. Also, you should seriously considering encapsulating the state of your object by making it private and implementing getters/setters.
Every class you call clone() on has to implement the Cloneable interface. From your comments, i understand your MyGraph class does not implement the Cloneable interface. In that case, Object.clone() throws the CloneNotSupportedException.
Trying to do deep copy with cloning is complicated as you need to ensure that all classes implement Cloneable interface and they have clone() definition.
Better way would be to do it through Copy Constructor or Serialization. Here is my blog on which i have discussed it in detail. hope it helps :)
A fundamental conceptual problem with cloning in Java [arguably the fundamental problem] is it's possible for a field of a type like List<String> to represent at least five very different things:
The only extant reference to a mutable list, which is used to encapsulate the mutable state thereof, but which--being the only extant reference--would not encapsulate its identity (the list could be replaced with a different list holding the same items, without altering the program's semantics). A correct clone of the object that contains this field would hold a reference to a different list holding the same items.
A reference to a mutable list which, while it would allow itself to be mutated, will never be exposed to anything that would actually mutate it. This reference may be shared with other code only if that other code will refrain from mutating the list or exposing it to code that might do so. A correct clone of the object that contains this field could hold a reference to either the original list or a different list holding the same items.
A reference to an immutable list. This reference may be shared freely with other code without regard for how that code might expose it. As above, the correct clone of the object containing this field could hold a reference to either the original list or a copy.
A reference to a mutable list which is owned by some other object, which is held for purpose of binding this to those aspects of the other object's state which are encapsulated in the list. A correct clone of the object holding the field must hold a reference to that same list, and not a copy thereof.
A reference to a mutable list which this object owns, but to which other objects also have a reference for purpose of either observing this object's state, or feeding information to this object. The object holding this field cannot be correctly cloned in isolation, though it might be possible to clone a group of inter-connected objects and give the new set of objects a set of interconnections which was isomorphic to those in the original group.
The concrete type of the object to which the field holds a reference may distinguish between some of the above cases, but it cannot distinguish among all of them. In particular, the first and fourth scenarios require different behavior on the part of the cloning method, despite the fact that in both scenarios the reference might likely pointing to an ArrayList<string>.
This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Java: how to clone ArrayList but also clone its items?
I have a sample program like the following:
ArrayList<Invoice> orginalInvoice = new ArrayList<Invoice>();
//add some items into it here
ArrayList<Invoice> copiedInvoice = new ArrayList<Invoice>();
copiedInvoice.addAll(orginalInvoice);
I thought I can modify items inside the copiedInvoice and it will not affect these items inside originalInoice. But I was wrong.
How can I make a separated copy / clone of an ArrayList?
Thanks
Yes that's correct - You need to implement clone() (or another suitable mechanism for copying your object, as clone() is considered "broken" by many programmers). Your clone() method should perform a deep copy of all mutable fields within your object. That way, modifications to the cloned object will not affect the original.
In your example code you're creating a second ArrayList and populating it with references to the same objects, which is why changes to the object are visible from both Lists. With the clone approach your code would look like:
List<Foo> originalList = ...;
// Create new List with same capacity as original (for efficiency).
List<Foo> copy = new ArrayList<Foo>(originalList.size());
for (Foo foo: originalList) {
copy.add((Foo)foo.clone());
}
EDIT: To clarify, the above code is performing a deep copy of the original List whereby the new List contains references to copies of the original objects. This contrasts to calling ArrayList.clone(), which performs a shallow copy of the List. In this context a shallow copy creates a new List instance but containing references to the original objects.
If you are storing mutable objects into the ArrayList, you will need to copy each object when you copy the ArrayList. Otherwise, the new ArrayList will still hold the original references.
However if you're storing immutable objects, it's fine to use:
ArrayList copiedInvoice = new ArrayList(originalInvoice);
I thought I can modify items inside the copiedInvoice and it will not affect these itmes inside originalInoice.
This happens because what gets copied is the reference variable and not the object it self.
Hence you end up with two "references" pointing to the same object.
If you need to copy the whole object you may need to clone it.
But you might have problems if you don't clone the object internal attributes if they happen to be other objects.
For instance the following class definition won't give you any problem.
public class Something {
private int x;
private int y;
private String stringObject;
}
If you create a copy of that, you would copy the current values of its attributes and that's it.
But if your class do have another object inside you might consider to clone it too.
class OtherSomething {
Something something;
private int x;
}
If you do the following:
Something shared = new Something();
OtherSomething one = new OtherSomething();
OtherSomething two = new OtherSomething();
one.something = shared;
two.something = shared;
In this case, both one and two have the same reference variable to the same shared "something" and changing the value in one would affect the other.
That's why it is much simpler/better/easier to use immutable objects.
If you need to change the value of an immutable object you just create a new one with the correct value.
Take a look at ByteArrayOutputStream and ByteArrayInputStream. If all of your classes implement Serializable, then you can make a copy using the above mentioned classes.
java.util.Calendar.clone() returns "...a new Calendar with the same properties" and returns "a shallow copy of this Calendar".
This does not appear to be a shallow copy as answered here on SO. That question is tagged language-agnostic, Java does not seem to follow the language agnostic definition. As I step through the code I notice that the structure and the elements are copied to this new object, more than the language agnostic structure only.
In Java, what is a shallow copy?
How does it differ from a Java deep copy (if that exists)?
A shallow copy just copies the values of the references in the class. A deep copy copies the values. given:
class Foo {
private Bar myBar;
...
public Foo shallowCopy() {
Foo newFoo = new Foo();
newFoo.myBar = myBar;
return newFoo;
}
public Foo deepCopy() {
Foo newFoo = new Foo();
newFoo.myBar = myBar.clone(); //or new Bar(myBar) or myBar.deepCopy or ...
return newFoo;
}
}
Foo myFoo = new Foo();
Foo sFoo = myFoo.shallowCopy();
Foo dFoo = myFoo.deepCopy();
myFoo.myBar == sFoo.myBar => true
myFoo.myBar.equals(sFoo.myBar) => true
myFoo.myBar == dFoo.myBar => **false**
myFoo.myBar.equals(dFoo.myBar) => true
In this case the shallow copy has the same reference (==) and the deep copy only has an equivalent reference (.equals()).
If a change is made to the value of a shallowly copied reference, then the copy reflects that change because it shares the same reference. If a change is made to the value of a deeply copied reference, then the copy does not reflect that change because it does not share the same reference.
C-ism
int a = 10; //init
int& b = a; //shallow - copies REFERENCE
int c = a; //deep - copies VALUE
++a;
Result:
a is 11
*b is 11
c is 10
Shallow copy is a just a set of pointers to the same memory locations. Actually it does not create a real copy so the memory usage is lower.
In a case of a deep copy, an exact copy of the memory segment is created and pointers are set to new memory locations. So theoritically the memory consumption should be twice in this case.
A shallow copy is a copy of the reference pointer to the object, whereas a deep copy is a copy of the object itself. In Java, objects are kept in the background, what you normally interact with when dealing with the objects is the pointers. The variable names point to the memory space of the object. A shallow copy is made when you set one variable equal to another like so:
Object B = A;
A deep copy could be made by getting the properties of object A and putting them in a new object B.
Object B = new Object(A.getProperty1(), A.getProperty2()...);
This affects program behavior in that if you make a shallow copy and perform a task on it, that affects all shallow copies of the object. If you make a change to a deep copy, only that copy is affected. I hope this is detailed enough for you.
The 1.6 docs document Calendar.clone as "Creates and returns a copy of this object." A literal shallow copy as specified by Object.clone wouldn't make any sense. Java uses the term "shallow copy" in a fairly typical sense.
It appears to be a mistake in the documentation. I don't see how anything that Android's Calendar.clone method does meets the typical definition (in Java or otherwise) of a "shallow copy".
SHALLOW COPY is PASS-BY-REFERENCE ...
DEEP COPY is PASS-BY-VALUE …
The context is different, but the process is exactly the same. First remember that in Java method calling, primitives are passed by value, while objects are passed by reference (in other languages, objects may also be passed by value). Now, in Java, when the caller passes a primitive to the called method, the called method simply clones it as a new local variable, which is a deep copy. While if an object is passed, the called method will only make a new local reference to the same object, which is shallow copy. If you understand calling, you understand deep/shallow copy, & vice versa.
Where are you getting this documentation?
The official Java 6 docs on java.sun.com simply have Calendar.clone() returning a copy of the object. No mention of shallow.
More generally, a shallow copy in Java is one where you get a new object reference but the new object holds (directly or indirectly) references to data in the original.
For example:
class MyClass{
private List<Integer> innerList;
public MyClass(List<Integer> list) { innerList = list; }
//Some code...
public Object clone(){
return new MyClass(innerList);
}
}
returns a shallow copy in its clone().
First of all, the Javadoc of ArrayList is somewhat wrong if we are talking about one-dimensional arrays, as it uses the method copyOf in Arrays. So clone() gives back a one-dimensional copy, at least since 1.5 (I didn't test further)! So that's what "shallow" means in Java: one-dimensional
You can read more here: http://www.javapractices.com/topic/TopicAction.do?Id=3. So clone() is no shallow copy! If you want a real shallow copy of a one-dimensional array, just reference it:
Array a = new Array();
Array b = a; //a is only a shallow copy, nice for synchronisation
Arrays in Java are tricky, also because Java does pass-by-value, but the values of arrays are only their pointers! In the other hand this allows us to synchronize the objects, which is a great thing. Still, there are some problems if you use arrays within arrays (or ArrayLists), because a clone() of the container array (or ArrayList) won't copy their values, only their references! So you simply shouldn't put any arrays into an array, you should only deal with objects in an array!
And Javadoc is difficult to understand sometimes, so give testing a try...
Have fun!
A shallow copy just copies the object reference into the target reference. It does not create a new object on the heap.
By default, Java does shallow cloning using clone() function.
To get a new object on the heap, one has to perform deep cloning which can be implemented by Serialization and De-serialization.
In a shallow copy,the clone object has a copy of primitive values but the object references refer to the same objects as the original copy.
Shallow Copies have a significant drawback, cloned object and original copy refer to the same address object. Any change that cloned object makes in address object will also be reflected in original copy, which is an unwanted behaviour. What we really wanted is two separate copies of user object. Deep copying comes to our rescue for this kind of situation.
Deep copying clones not just the primitive values, it also creates copies of object references.
You can have a look at working example on this at here :https://codingninjaonline.com/2017/11/09/deep-vs-shallow-copy/
Shallow Copy : In this cloning any changes to Cloned Object is reflected to Original Object also.
Deep Copy : In this cloning a separate cloned memory is alloted which means any changes to cloned object will not be reflected to original object.