How do I make defensive copies of a Mutable Object which contains a mutable field in an Immutable Object?
class ImmutableObject {
private final MutableObject immutable_field;
ImmutableObject(MutableObject y) {
this.immutable_field = y;
}
}
class MutableObject {
public int mutable_field;
}
The MutableObject does not have a constructor that lets me set the field.
The MutableObject's current state should be captured in the Immutable Object and never changed.
What you need to do is in
MutableObject return_immutable_field() {
return immutable_field;
}
Change to:
MutableObject return_immutable_field() {
MutableObject tmp = new MutableObject();
tmp.mutable_field = immutable_field.mutable_field;
return tmp;
}
For an explanation see http://www.javapractices.com/topic/TopicAction.do?Id=15
Well, assuming that there is nothing to be done about the declaration of the mutable object class, one could leverage reflection (Class.newIntance() and Class.getFields()) to create a new object and copy field values. You could also implement deep copying in this manner. If the class supports serialization, then another hackish approach would be to serialize the object and then save a deserialized copy. If it is possible to fix the design of the mutable object, though, that would be a better approach.
Edit
For the particular example that you've given, Romain's answer does what you want. If you have a general mutable object that doesn't provide a mechanism for copying it and for which the type may not be known until later, then the reflection approach is how one would implement a copy mechanism.
Related
I ran across this problem, which has been driving me nuts. In a nutshell, I instantiate two objects of the same class. When I run a method in one object, the other object is affected too as if I called a method on a 2nd object explicitly. I was wondering if someone could please give me a hand on this.
Suppose, I have class Portfolio...
public class Portfolio implements Cloneable {
public ArrayList<Instrument> portfolio;
private String name;
private String description;
public Portfolio() {
portfolio = new ArrayList<Instrument>();
}
public Portfolio(Portfolio copyFrom) {
//attempt to copy the object by value
this.portfolio = (ArrayList<Instrument>) copyFrom.portfolio.clone();
this.name = copyFrom.name;
this.description = copyFrom.description;
}
public void applyStress(Stress stress) {
this.portfolio.set(0,this.portfolio.get(0)+1;
}
1st constructor is used to instantiate an object, etc. 2nd constructor is used to copy an object by value.
A method applyStress is used to run through sum calculations. in our case I simplified the method, so that it does nothing but adds +1 to whatever is in the object.
So I would instantiate an object as
Portfolio p = new Portfolio();
then I would assign to a portfolio field, some instruments;
p.portfolio = someInstrumentList;
then I would copy by value the portfolio p into pCopy:
Portfolio pCopy = new Portfolio(p);
So at this time I am have two objects that are the same. Further one is a copy-by-value object. Changing values of fields in pCopy does not affect same fields in p.
Now, when I run a method applyStress on p, then the values of the instrument list in pCopy will also change.
In other words, if p.portfolio.get(0) == 1, then after p.applyStress, I would expect to see that p.portfolio.get(0) is 2 and pCopy.portfolio.get(0) is 1
But what I see instead is p.portfolio.get(0) is 2 and pCopy.portfolio.get(0) is also 2
I do not understand why this happens. It is not the static modifier issue, as there is no static modifiers. Anyone has any ideas?
The clone method applied to you your ArrayList reference does a shallow copy, not a deep copy. This implies that whatever you had in the original collection is shared by the cloned one.
This means that you need to clone every instrument as well, or provide a copy constructor for every one of them.
this.portfolio = new ArrayList<Instrument>();
for(Instrument toBeCopiedInstrument : copyFrom.portfolio){
this.portfolio.add(new Instrument(toBeCopiedInstrument ));
}
By default .clone() does what is called a shallow copy, this means it just copies a reference to the objects that are held in the List that is being cloned, it doesn't actually copy the objects themselves to new instances.
What you need to do is implement a custom deep copy for the List and each of the items held in the list. But deep clone is a broken concept and implementation in Java.
A copy constructor isn't a really good pattern in Java either, because you end up copying references as well in most cases and every object you inject to the constructor has to follow the same copy constructor semantics all the way down the chain. Unlike C++, this is manual, tedious, unmaintainable and error prone process!
.clone() and implements Cloneable are some of the most complex to get correct concepts in Java. They are rarely needed in well designed applications. That is, if you are using .clone() you are probably doing it wrong. If making bit wise copies of your objects are part of your design for something other than storage, you might want to revisit your design.
Josh Bloch on Design
Object's clone method is very tricky. It's based on field copies, and
it's "extra-linguistic." It creates an object without calling a
constructor. There are no guarantees that it preserves the invariants
established by the constructors. There have been lots of bugs over the
years, both in and outside Sun, stemming from the fact that if you
just call super.clone repeatedly up the chain until you have cloned an
object, you have a shallow copy of the object. The clone generally
shares state with the object being cloned. If that state is mutable,
you don't have two independent objects. If you modify one, the other
changes as well. And all of a sudden, you get random behavior.
Immutable
A better pattern is to make everything immutable. That way you don't need separate instances, you can share instances until they need to change, then they change and you have a new instance with the new data, that can be shared without any side effects.
I have a class (Literal). I need to be able to keep an intact Literal instance in memory throughout my application, and have a copy of it which I can alter. I have used two ways to do this:
class Literal implements Cloneable and override Object.clone() method.
Factory constructor:
public Literal(Literal lit){
this = lit;
}
In both cases copying doesn't work. Every change I make to the copy, changes the original. Does anybody have any idea what I'm doing wrong?
since Literal is not a integral type, variables of type Literal holds a reference to the actual value, so this = lit just copies the reference, so your behavior.
You must copy all the member fields recursively to do a "real" copy.
This article has been linked in the accepted answer to the question linked by Umesh in his comment, and I think it clears the conceptual problems you're hitting with your problem.
If you are going to use copy-constructor, then you will need to make a deep copy of every mutable member variable.
Say your Literal has member variables like this:
private String[] args;
private String s;
Then your copy-constructor would need to do something like this
public Literal(Literal l) {
// have to deep copy the array, otherwise both instances are sharing the reference
this.args = Arrays.copyOf(l.args, l.args.length);
// safe to just copy the reference, String is immutable
this.s = l.s;
}
Why do we use the clone() method in Java? (Please give the answer in respect of memory constraint.) Will that reduce memory usage? If yes, then how? Will that reduce the effect of memory leak?
Apart from do not use clone, implement a copy constructor, you asked about memory constraints.
The idea of cloning is to create an exact duplicate of the cloned object. So in worst case, you use twice the amount of memory afterwards. Practically - a bit less, because Strings are often interned and will (usually) not be cloned. Even though it's up to the implementor of the clone method/copy constructor.
Here's a short example of a class with a copy constructor:
public class Sheep {
private String name;
private Fur fur;
private Eye[2] eyes;
//...
// the copy constructor
public Sheep(Sheep sheep) {
// String already has a copy constructor ;)
this.name = new String(sheep.name);
// assuming Fur and Eye have copy constructors, necessary for proper cloning
this.fur = new Fur(sheep.fur);
this.eyes = new Eye[2];
for (int i = 0; i < 2; i++)
eyes[i] = new Eye(sheep.eyes[i]);
}
}
Usage:
Sheep dolly = getDolly(); // some magic to get a sheep
Sheep dollyClone = new Sheep(dolly);
We should not use it. It is a broken and obsolete idiom, which should be avoided in new code. Better use a copy constructor instead whenever you can.
The clone() copies the values of an object to another.
clone() method saves the extra processing task for creating the exact copy of an object.
As you can see in the below example, both reference variables have the same value.
class Student18 implements Cloneable {
int rollno;
String name;
Student18(int rollno, String name) {
this.rollno = rollno;
this.name = name;
}
public static void main(String args[]) {
try {
Student18 s1 = new Student18(101, "amit");
Student18 s2 = (Student18) s1.clone();
System.out.println(s1.rollno + " " + s1.name);
System.out.println(s2.rollno + " " + s2.name);
} catch (CloneNotSupportedException c) {
}
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Output :
101 amit
101 amit
If we create another object by new keyword and assign the values of another object to this one, it will require a lot of processing on this object. So to save the extra processing task we use clone() method.
if we need to use many object having the same data, then don't create objects using new keyword. use clone method to create that object, because operation of creating object with clone method is faster than using new keyword.
Making a copy of an object seems at first to be a straight forward task:
Simply copy the values of all the properties into another instance of the same class.
But what about the variables that are references to other objects? Copies of these reference values mean they will point to the same objects as the first class.
But maybe that is not what we want. Perhaps we want all the objects referenced by the copy to be independent copies as well.
These two types of object copies are called:
shallow copy - exact bit copy of all the attributes of the original object
deep copy - primitives are copied exactly but objects referenced are copied rather than the references themselves.
The Object class, which is inherited by all Java classes, includes the clone() method that will make exact bit copies of all the properties.
However, clone() is a protected method. So a given object can not be cloned by instances of any classes outside the package (unless they are subclasses of that object's class). This allows the class designer to specify explicitly what kind of clones (shallow or deep) to make.
Java requires classes that want to override the clone() method, to implement the cloneable interface. The clone() method must be made public as well so as to override the access restrictions.
For example, the HashTable class implements cloneable. Its clone() method makes a shallow copy so the keys and values of the copied HashTable will reference the same objects as the original.
Many core Java classes, however, do not implement cloneable. If the clone() method is invoked for such classes, a CloneNotSupportedException will result.
see clone constraints
in few words it is used to copy the objects instead the references, it increase the memory usage.
We should avoid using clone()
Here is good example
I'm coming from the C++ world and I can't find what is the Java alternative (if any) to the following:
struct SomeStruct
{
SomeStruct(){}
SomeStruct(const SomeStruct& rhs)
{
*this = rhs;
}
};
The reason why I need this is that I have a cache of existing objects, so I don't want to create another instance but just to 'clone' the existing one, something like this:
public class SomeObject
{
private static Hashtable _objects;
SomeObject()
{
SomeObject obj = _objects.get(some_key);
if (obj != null) {
// *this = obj;
// instead of:
// this.something = obj.something;
// this.something1 = obj.something1;
// this.something2 = obj.something2;
// a zillion fields....
}
}
};
EDIT:
Sorry, I confused some things (still need to learn both Java and C++).
Thank You
The closest is Object.clone() but read the relevant section from Effective Java first.
There are probably simpler ways to do what you want if you remove some of your requirements. For example, if you make your objects immutable then you don't need to copy the data into another object. Instead you can return a reference to the original object. This is much faster than a memberwise copy, and has lots of other benefits too, such as making it easier to write thread-safe code.
There's no direct equivalent. Object.clone() is the closest, but it creates a new instance and performs a shallow copy. You could write something generic using reflection though.
public class SomeObject
{
private static Hashtable _objects;
public static SomeObject getInstance(SomeKey some_key)
{
return _objects.get(some_key);
}
}
It is unclear from your question whether you are trying to achieve a pure cache of immutable objects, or keep a cache of 'template' objects, and return copies that can then be mutated by the client. I am going to assume the latter.
Assuming that you do want to return copies of originals. there is no really nice way to implement a copy constructor in Java. Clone is marginally nicer, so you should hide the constructor behind a static factory method:
public static SomeObject getInstance(...) {
SomeObject cached = ...;
if (cached != null) {
return cached.clone();
}
...
}
Perhaps in your particular case you can separate the immutable and stateful parts of the objects? If so, some changes to your object model can lead to cleaner (and more efficient) code?
In Java, if you want to have a constructor corresponding to a copy constructor, you have to implement it yourself. In some cases, this means you have to copy fields from one object instance into another, while in other cases it means you have to implement a full deep copy - recursively iterate through the reference fields of the parameter in the copy ctor.
This depends on what you want - should the objects hashtable be copied as well? Or should both objects share the reference to it? For more info, see this question.
I don't know of any generic way to copy all the contents of fields from one object to another existing without using;
reflections
generated code.
copy using the Unsafe class.
Reflections is easier to use at runtime, but not as efficient as generated code. (But pretty close) I generate my data model so I use this option.
The Unsafe class is faster than reflection, but not cross platform and unsafe. It is almost as fast as generated code. ;)
In terms of speed, if generated code is 1x, Unsafe is 1.5 - 2x and reflection is 2 - 4x slower for highly cached data. For poorly cached data you won't see a difference.
You should use the Singleton pattern. You create a static instance of SomeObject and work with that instance.
private static class SingletonHolder {
public static final SomeObject INSTANCE = new SomeObject();
}
public static SomeObject getInstance() {
return SingletonHolder.INSTANCE;
}
But don't fall in the Singleton trap, limit calls to getInstance()!
In a software development class at my university, the teacher kept mentioning that on a quiz we needed to make sure that a field returned by a getter needed to be "protected." I guess she meant that nothing outside the class should be able to change it. She didn't give much more of an explanation than that.
For instance:
class Foo {
string[] bar = <some array contents>;
public string[] getBar() {
return bar;
}
}
Any code calling getBar would be able to modify the elements in that array. How do you prevent that from happening? I'm assuming that the object itself should be able to modify the array, just not anything outside the object.
This isn't homework help since the quiz is a couple of weeks old. I simply want to understand Java better since my teacher didn't explain very well.
Update: The teacher wouldn't merely allow us to use protected as the access modifier on the field.
You either use a collection and wrap it in Collections.unmodifiable*() or you defensively copy your array, collection or object if its mutable (which arrays always are).
For example:
class Foo {
private String[] bar = <some array contents>;
public String[] getBar() {
return bar == null ? bar : Arrays.copyOf(bar);
}
}
What you have to watch out for is that this is a shallow copy (so is clone). Not sure what your teacher's problem with clone was.
Just to add to one of the previous answers, you want to make sure that with a collection you aren't using the clone() method to achieve what you are trying to achieve here. This creates a shallow copy of the collection only, all object references contained in the collection copy still point to the same objects as in the original, e.g. the objects in the collection copy can still be modified, even though the original collection cannot. Be sure you are making a deep copy of a returned collection if this is what you are trying to do.
I suspect what she meant was that the visibility of the field itself should be protected (or private) so that access only occurs through the getter. In the case of a collection, you may also want to do as #cletus suggests and return a copy of the collection if you don't want it to be modified outside the class. EDIT Based on your edit, she probably meant both.
class Foo {
protected string[] bar = <some array contents>;
public string[] getBar() {
return bar;
}
}
To protect that field from being changed you need to first make it private and don't provide any setter of any other method which changes that field. This way nobody can change the reference of that variable.
If the field is a mutable Object then again its value can be changed. For that you would need to do deep cloning before returning that object.
I'd add to cletus' first suggestion - the easiest way of making bar immutable would be to use a List instead of an array and return it wrapped in an unmodifiableList. That way it's immediately clear to the client of the class that the contents of bar can't be altered - an UnsupportedOperationException is thrown. Messing about with deep cloning will probably be pretty inefficient, depending on the complexity of your objects, and still returns a bunch of mutable objects - it's just that any changes made to those will be ignored by Foo.
class Foo {
private List<String> bar = new ArrayList<String>();
public Collection<String> getBar() {
return Collection.unmodifiableList(bar);
}
}
(Also might be worth noting that with generics in Java 5+, a list behaves much more like an array than it used to).
Please tell the professor that all non-final fields must be private to preserve encapsulation.
Protected allows your subclass or other classes in the same package to modify the field without your class knowing it.
The only class that should touch non-final fields directly is the class that defines them.
(Think about what would happen if you wanted to later fire an event when the field changes... you can only do that if all access is through the setter...)