Java return copy to hide future changes - java

In Java, say you have a class that wraps an ArrayList (or any collection) of objects.
How would you return one of those objects such that the caller will not see any future changes to the object made in the ArrayList?
i.e. you want to return a deep copy of the object, but you don't know if it is cloneable.

Turn that into a spec:
-that objects need to implement an interface in order to be allowed into the collection
Something like ArrayList<ICloneable>()
Then you can be assured that you always do a deep copy - the interface should have a method that is guaranteed to return a deep copy.
I think that's the best you can do.

One option is to use serialization. Here's a blog post explaining it:
http://weblogs.java.net/blog/emcmanus/archive/2007/04/cloning_java_ob.html

I suppose it is an ovbious answer:
Make a requisite for the classes stored in the collection to be cloneable. You could check that at insertion time or at retrieval time, whatever makes more sense, and throw an exception.
Or if the item is not cloneable, just fail back to the return by reference option.

Related

Cloneable and Collection

I am trying to code my own version of ArrayList (to learn how it works) and I was looking at the Cloneable interface which is implemented by java.lang.ArrayList (I would like to keep the same contract than the original version).
I am a bit confused by the definition of the clone() method and hope someone can clarify it for my case.
The part I am not really sure of, is that if someone use the clone() method on my collection, it should return a new ArrayList (meaning not a reference to the existing one).
However:
Does it means that each object contained needs to be cloned as well?
Do I have to explicitly create a new instance using 'new' for each of them (which should be quite slow?)
Should I be trying to use the clone() method on my collection's objects, and how to be sure they override the clone() method as the definition in Cloneable states that it is not explicitly required (the method is not in the Interface)?
Thanks in advance for any help.
In the context of a Collection the contract is to get a new Collection with the same objects, not copies or clones of the objects. Anything else would break the contract.
So what you want is a "shallow" copy of the elements, just their references, in the new collection. What you are suggesting with the cloning/new is a "deep copy" which is very different, and you shouldn't do in this case.
So
You definitely should not clone each of the objects in the Collection.
Same as 1. You should not use new, this would be doing a "deep" copy of the collection.
No, same as 1. 2.

Is it bad design to pass reference of collections in constructor?

I encounter many times of similar code:
class AClass{
private Iterable<String> list;
public AClass(Iterable<String> list){ this.list = list; }
...
}
In this code, a reference of Iterable is passed to AClass directly. The end result is equivalent to directly expose list reference to outside. Even if you make AClass.list final, it still allows code from outside AClass to modify the content of the list, which is bad.
To counter this, we will do a defensive copy in the constructor.
However, this kind of code is very common. Besides performance consideration, what's the intension for people to write this kind of code?
I don't see anything wrong with that pattern. If the class represents objects that operate on a list (or an iterable) then it's natural to provide that list to the constructor. If your class can't handle changes to the underlying collection, then it needs to be fixed or documented. Making a copy of the collection is one way to fix that.
Another option is to change the interface so that only immutable collections are allowed:
public AClass(ImmutableList<MyObject> objects) {
this.objects = objects;
...
You would need some kind of ImmutableList-class or interface of course.
Depending on the use and users of your classes you could also avoid making copies by documenting the known "weakness":
/**
* ...
* #param objects list of objects this AClass-object operates on.
* The list should not be modified during the lifetime
* of this object
*/
public AClass(List<MyObject> objects) ...
Simple answer, if it is your own code/small team, it is often just quicker, easier and less memory and CPU intensive to do things this way. Also, some people just don't know any better!
You might want to take a look at the copy constructor for a familiar idiom.
Its always good practice to make a copy, not only because other people can then modify your values, but also for security reasons.
If the code is being used internally as is pointed by other answers it should not be a problem. But if you are exposing as an API then there are two options:
First is to create a defensive copy and then return it
Second would be to create a UnmodifiableCollection and then return it and document the fact that trying to change anything in the collection may result in exception.
But the first option is more preferable.

Creating a copy of a TreeSet or any Collections for that matter

I have a treeSet of custom objects. Each custom object is made up of int a, int b, String c and double d. Lets say I have a treeSet object t1 containing 10 such custom objects. I also have another TreeSet object t2 which is empty. what is the best way of copying the objects in treeset t1 into treeset t2... I want new objects in t2 and not just refernces to the ones in t1.one way is to create 10 new objects in t2 and copy the values of all the a's and b's and c's and d's of each of the 10 objects in t1 to those in t2. Any better way?
This technique is known as "deep copying" and there's a good Stack Overflow question on it here.
The current top two answers provide two good perspectives:
Serialize your objects and then deserialize them (efficient, but not 100% reliable) -- link to answer
or you'll just have to traverse the whole object and do it manually (as reliable as you can get but not super-simple to do) -- link to answer
for (Item item : collection) {
newCollection.add(BeanUtils.cloneBean(item));
}
where BeanUtils is from commons-beanutils
Override the clone() method in your custom object
Iterate over the source collection
Add the cloned items to the destined collection.
Depends on what you mean by better. The best solution is to make the object immutable and just copy the references.
An alternative is to generate or write a copy constructor. The copy constructor can use reflections to copy all the fields.
For the field types you have, you can make the Object Cloneable and use the clone() methods. (Because the fields are primitives or immutable)
You already got your answer.
However this process is best to be implemented in the clone() method. So all your object should overwrite this method.
See an example here: http://www.roseindia.net/java/example/java/util/clone-method-example-in-java.shtml

Best Practice for Returning Object References

Consider this code snippet:
class MyClass{
private List myList;
//...
public List getList(){
return myList;
}
}
As Java passes object references by value, my understanding is that any object calling getList() will obtain a reference to myList, allowing it to modify myList despite it being private. Is that correct?
And, if it is correct, should I be using
return new LinkedList(myList);
to create a copy and pass back a reference to the copy, rather than the original, in order to prevent unauthorised access to the list referenced bymyList?
I do that. Better yet, sometimes I return an unmodifiable copy using the Collections API.
If you don't, your reference is not private. Anyone that has a reference can alter your private state. Same holds true for any mutable reference (e.g., Date).
It depends on what you want.
Do you want to expose the list and make it so people can edit it?
Or do you want to let people look at it, but not modify it?
There is no right or wrong way in this case. It just depends on your design needs.
There can be some cases when one would want to return the "raw" list to the caller. But in general, i think that it is a bad practice as it breaks the encapsulation and therefore is against OO.
If you must return the "raw" list and not a copy then it should be explicitly clear to the users of MyClass.
Yes, and it has a name.. "Defensive copy". Copying at the receiving end is also recommended. As Tom has noted, behavior of the program is much easier to predict if the collection is immutable. So unless you have a very good reason, you should use an immutable collection.
When Google Guava becomes part of the Java standard library (I totally think it should), this would probably become the preferred idiom:
return ImmutableList.copyOf(someList);
and
void (List someList){
someList = ImmutableList.copyOf(someList);
This has an added bonus of performance, because the copyOf() method checks whether the collection is already an instance of immutable collection (instanceof ImmutableList) and if so, skips the copying.
I think that the pattern of making fields private and providing accessors is simply meant for data encapsulation. If you want something to be truly private, don't give it accessor methods! You can then write other methods that return immutable versions of your private data or copies thereof.

How do I copy an arraylist from one class to another in Java?

I understand that in order to copy an arraylist and have two lists independent of one another you must use a deep copy (copying the objects from one list to another not just the references), however is there a way this can be done cross-class?
For example; I am calling Class2 from Class1. In Class2 objects are added to an ArrayList of custom objects upon an event. I would like to be able to transfer this ArrayList to Class1 but whenever I try I get a NullPointer.
Any clues??
This is highly indicative of a design flaw.
See if you can't accomplish the same goal by wrapping your list in a class, sharing the class and using it to control access to the list.
The only case where this wouldn't just outright work is if your two classes must modify the list independently.
If this is a requirement, then I would probably hand a different instance of the wrapper class to each modifying class (with a reference to the same source list), then have a way for newly added data to be tagged with an ID referring to the original class--that way when you query, the wrapper would only return untagged items (items that were part of the original shared list) and items tagged with it's own ID.
Either that or the wrapper class could contain a second list and when queried, return the combined results of the original and second lists.
I've almost never wanted a deep copy. It happens, but it's quite rare.
If you post more info, maybe we can be more specific in helping with the redesign.
ALSO: (Edit)
Chances are that the copied array list isn't your problem--it's probably that it wasn't TRULY a deep copy. For a deep copy, it means you implement a copy method (I believe they are supposed to be called .clone(), I never use this stuff--as I said, it's bad juju) for each object in the array list, then you call your copy method on each one to get the new copy in your next list.
Furthermore, any objects referenced by your copied object should probably be cloned as well. "Deep" means all the way down the tree.
I'm guessing you're failing somewhere in the process.
I'd really like to hear why you feel you need a copy instead of a reference.
My suggestion is for you to create a getArray() method and call it from the other class. This method should create a copy of the ArrayList because you should not "transfer" variables within classes; always with get() method so OO paradigm stays intact.
Do something like this:
Class 1
public ArrayList<Object> getArray() {
ArrayList<Object> aux = new ArrayList<Object>();
for(Object x : list) //object is the string, int, etc...
aux.add(x.clone()) //assuming the Object has a clone method!
return aux;
}
On Class 2, just call this method. Then just look at the test from the other answer about the null exception, should work.
Hope it helps.

Categories