How do I do a Java-deep copy of an object? - java

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;
}

Related

In java, is an object considered a variable?

One source I am studying defines an array as "a collection of variables under one name, where the variables are accessed by index numbers."
But then I realized that you can have an array of objects (or an array of pointers to objects, at least).
This got me to wonder what a variable is defined as in java, as I did not consider an object to be a variable. Jenkov Tutorials cites a variable as being "a piece of memory that can contain a data value."
And since I believe an object fits this definition, is an object considered a variable?
Calling an array a "collection of variables" is arguably stretching the definition already. But an array is certainly a collection of references that can be made to point to different objects in memory, and each such reference can reasonably be called a variable.
Asking "is an object a variable" is a little weird in the first place. In Object o = new Object(), o is clearly a variable, though remember it's a reference to an object in the heap, not the object itself.
Honestly, "variable" is a pretty flexible, ill-defined term -- is a field a variable? The return result of a method? It depends on who's talking and what fuzzy definition they're using today.
is an object considered a variable?
No, these are two distinct things.
The first one (the object) is the value and the second one (the variable) is a way to reference an object, generally to use it (invoking a series of method on it for example).
For example when you write :
new Dog()
You instantiate a Dog. Nice. But suppose you want feed it if it is hungry.
You cannot if you have not a way to chain a series of method on this object.
By storing the reference of the Dog in a dog variable you can do it :
Dog dog = new Dog();
if (dog.isHungry()){
dog.feed();
}
Jenkov Tutorials cites a variable as being "a piece of memory that
can contain a data value."
It says the same thing.
But this :
One source I am studying defines an array as "a collection of
variables under one name, where the variables are accessed by index
numbers."
is rather misleading.
An array is an object that has a state that contains, among other things, elements of the array.
The way which the elements are referenced in is a implementation detail of the Array class and I would not affirm that each element is stored in a specific variable.
An object is created when you call the constructor with the reserved word new.
For example:
Object a = new Object();
a will be the variable of that new object created and will go to reserved memory for that object. You are instantiating that new variable and that variable is associated with that object.
Hope might this will help you to understand it better...
class Bulb
{
private int w;
public void setWattage(int e)
{
w=e;
}
public int getWattage()
{
return w;
}
}
class Test
{
public static void main(String args[])
{
Bulb b[];
b=new Bulb[2];
b[0]=new Bulb();
b[1]=new Bulb();
b[0].setWattage(60);
b[1].setWattage(100);
System.out.println(b[0].getWattage());
}
}
here b[0] and b[1] are reference variables who have the address of two Bulb objects

Method runs for all instances of a class

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.

Why do we use the clone() method in Java?

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

How do I make defensive copy of an object?

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.

In Java, Prevent a field from being changed after being returned by instance method

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...)

Categories

Resources