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
Related
As we know java does not support call by reference and also it's true that if with copy constructor we use call by value then the copy constructor would call itself recursively infinite times.Then how copy constructor do work in java??
Thanks in advance.
The closest equivalent to a copy constructor in Java is overriding the clone() method of the Object class. The javadocs do a fairly good job at explaining its usage.
if with copy constructor we use call by value
There is no copy constructor built-in to Java. You can create one of your own but this is only used when you explicitly call it. To Java it is just another constructor which has no special meaning.
Java only has primitive and reference variable and when these are copied, no method or constructor is called.
e.g. In this example, it is the reference which is copied, not the object.
Integer i = 5; // A *reference* to an Integer object.
Integer i = j; // A *reference* to the same object.
copy constructor would call itself recursively infinite times.
A common misconception is that Java has Object variable types when it doesn't.
Java copy constructor for any object is a deep copy of this object.
For example,
public Car(String motorShow, double price) {
this.motorShow = motorShow;
this.price = price;
} ^ ordinary constructor for a Car object
//the copy constructor for Car:
public Car(Car other) {
this.motorShow = other.motorShow;
this.price = price;
}
/* Simply in the main class write Car c2 = new Car(c1);
this basically will create a copy of c1 of, and note that changing the attributes of one of the objects won't affect the other since it's a deep copy; unlike this for example:
Car c1 = c2;
here, changing any attribute of c1 or c2 will affect the other, i.e two pointers for the same space or reference in memory */
I hope this helps.
I'm trying to understand this operator function written in C++ and convert it to Java.
Class& Class::operator=(const Class& In) {
properties = In.properties;
return *this;
}
Does this simply copy instance and properties of a class object? For which I've already written something:
public static Class copy(Class obj) {
//returns new instance of Class individual
Class copy = new Class(obj.row_num, obj.col_num, obj.input_length, obj.output_length, obj.max_arity, obj.function_length, obj.levels_back);
copy.genes = obj.genes.clone();
return copy;
}
Am I on the correct track? Many thanks for your help.
Ampersand & designates a reference in C++. It is needed to provide the behavior similar to what Java objects provide "out of the box", because Java manages objects through references.
There is no copying going on in C++ when a reference is passed. In fact, avoiding copying is a major reason for using const references as function parameters.
The code that you show does not perform copying either: it changes its state based on the value being "assigned". The closest way of modeling this in Java would be providing an assign(Class other) method that changes the current state to match that of the object passed in:
Class assign(Class other) {
this.properties = other.properties;
return this;
}
You will need to use this method in place of C++'s assignment, like this:
Class clOne(args1);
Class clTwo(args2);
clOne = clTwo; // Using the assignment operator
becomes this:
Class clOne = new Class(args1);
Class clTwo = new Class(args2);
clOne.assign(clTwo); // Using the assignment method instead of the operator
You're pretty much on the right track. The copy assignment operator in C++ is used when directly assigning (copying) from one object to another. As Java objects are only accessible via references, such assignments are meaningless. To match the C++ semantics exactly, the Java equivalent would be:
public Class copy(Class obj) {
row_num = obj.row_num;
col_num = obj.col_num;
// etc., etc.
genes = obj.genes.clone();
return this;
}
Am I on the correct track?
Kind of. But not quite. C++ distinguishes between reassigning an existing object and creating a new one.
Java doesn’t. You cannot reassign to an existing object in Java1 (but you can of course reassign a reference). In Java, in order to copy an object (rather than assign a reference to it), you would usually use a copying constructor:
Class(Class other) {
// Copy members of `other` into `this`.
}
And then use it as follows:
Class x = new Class(something here);
Class y = new Class(x); // copy
In particular, this is what all the Java containers implement. I would not rely on clone. First of all, clone should only be used if the class implements the tag interface Cloneable. Second of all, clone’s design is arguably broken and its use is not recommended.
1 Well you could of course reassign the members of an object (unless they are final), and you could mimic C++’s copy assignment operator by providing a method assign to do that. However, this isn’t the conventional way of doing things in Java (although it might have its place in some exceptional instances).
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;
}
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.