Why isn't there a easy way to copy objects in Java? - java

I have a class TimeLine in my GUI. I have a function where I would like to copy this TimeLine and modify the data in it whithout the TImeLine in my GUI won't be affected.
I've searched some forums and haven't found an easy way because Java let's the references stick. Why isn't there a easy way to create a new Object (TimeLine) that hasn't the reference to the previous one?
Please help my make a copy of this TimeLine object!

The clone() method and Cloneable interface, suggested by other authors here, were created with the incorrect assumption that it would be a good idea to have a generic copying method. The default implementations does a shallow clone of the current object, but you could override it to do a deep clone.
There is no correct, generic way to copy arbitrary objects, what you want to copy depends on the objects involved. For example, immutable objects never need copying (that'd just be a waste of space), while some types of objects can't be copied (how would you copy a FileOutputStream, for example?).
The way I find most elegant is immutable objects with methods that return a copy with just one field changed:
class Pony {
private final String name;
private final Color color;
private final int tailLength;
// constructors and accessors omitted
Pony withName(String newName) {
return new Pony(newName, color, tailLength);
}
Pony withColor(Color newColor) {
return new Pony(name, newColor, tailLength);
}
Pony withTailLength(String newTailLength) {
return new Pony(name, color, newTailLength);
}
}
// Usage:
Pony tony = new Pony("Tony", Color.DAPPLE, 32);
Pony maurice = tony.withName("Maurice") // Maurice is like Tony, but black.
.withColor(Color.BLACK);
Unfortunately, you get a lot of boilerplate this way, and there's no mainstream IDE support either (there may be plugins, though). Related to this is the Builder pattern recommended by Josh Bloch in Effective Java.

Instead of clone() you might want to consider writing a copy constructor for your class:
public TimeLine(TimeLine original) {
this.foo = original.foo;
this.bar = original.bar;
}
Be careful when copying the value of any reference fields in your class. Be sure whether you want a shallow copy or a deep copy.

In Java using the operator "=" your are simply copying references to objects. If you want to implement copy by value use clone operation (clone() method of the class Object) or implement your own clone method (overriding the implemented one).
Pay attention that if your class stores other object inside it, these objects should eventually be cloned too (DEEP COPY).

if you want to copy an object use clone()
if I misunderstood your question please comment

You're looking for the clone method. (I've gone back and forth as to which documentation to cite, that is Wikipedia, it's treatment is more thorough. The Java doc's are more official, of course).
Eg.
MyObject a = new MyObject();
a.setSomething( 2 );
MyObject b = a.clone();
// now b.getSomething().equals(a.getSomething()) (maybe == too, depends on class)
// and b.equals(a)
// b != a

Related

How do I implement a getter where the caller can't edit the returned object?

I want to make a getter that doesn't allow the caller to edit the returned object.
Using a List as an example (though I would like the answer to apply to any other type as well), this is the usual approach for returning and for editing an attribute:
class MyClass {
private List<String> strings;
// to get the whole object
public List<String> getStrings() {
return this.strings;
}
// to alter the object
public void addString(String newStr) {
this.strings.add(newStr);
}
//...
}
However, this doesn't prevent that some other class from doing this
myClassInstance.getStrings().add("that's a dumb implementation, bro");
and that would be kind of rude since I created addString() for that specific purpose.
I would rather if other classes would only use the getStrings() method for reading, because there might be a similar case where I don't want to implement the addString() method. In that situation, other classes are able to edit strings anyway through the getter, but I still want to be able to edit the object privately in the C class.
I know this wouldn't be a problem if the attribute was a primitive type since those are saved directly in the instance, but objects are references to memory, so any class that's able to get its hands on those references can edit it if the object type allows that.
Can I just trust that other classes won't try to edit my object through the getter?
There's the option of cloning it (some classes may override the clone() method), but is this a good use for clone()? What are the best practices of cloning an object?
Is it worth it to create a custom class (called ReadOnlyList, for this example) that is only writeable in the constructor (like this), then copy my strings to a new ReadOnlyList, and return that?
Also, should objects provide a method that returns a non-writeable clone of the object to solve this?
You can have getStrings return an unmodifiable list.
public List<String> getStrings() {
return Collections.unmodifiableList(this.strings);
}
https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#unmodifiableList(java.util.List)
Can I just trust that other classes won't try to edit my object through the getter?
No.
There's the option of cloning it (some classes may override the clone() method), but is this a good use for clone()? What are the best practices of cloning an object?
The oracle docs provide a proposed strategy:
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods. (https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html)
Is it worth it to create a custom class (called ReadOnlyList, for this example) that is only writeable in the constructor (like this), then copy my strings to a new ReadOnlyList, and return that?
In this case not (see Micky Loo's answer). However in a more special case yes (if you have to guarantee immutableness and can not copy the object).
Also, should objects provide a method that returns a non-writable clone of the object to solve this?
You can not create a const return value in Java. see: Const return values in Java

Simple deep copying method in Java

I am trying my hand at deep copying in Java. So far I have implemented the following method in the class (Example) whose objects I would like to get deep copies of (parameter1 and parameter2 being the parameters needed by the constructor of the Example-class to create an object of the latter):
public Example clone(){
Example clone = new Example(this.parameter1, this.parameter2);
return clone;
}
So basically I clone an object by calling the constructor of the corresponding class and by using its current attributes as parameters for that constructor.
My problem is that this seems a bit too simple to be true. Especially since the solutions I looked up online were much more complex. So I'm wonderin what the hook is with my method.
Any hint/explanation will be greatly appreciated.
EDIT:
This is the constructor for the Example-class:
public Example(double parameter1, double parameter2){
this.parameter1 = parameter1;
this.parameter2 = parameter2;
}
With primitives it is relatively simple. But if you had any fields that were not primitive, just using that copy constructor would only result in a shallow copy of that object. Meaning you would be using the same object for your field between the classes.

Looking for a concise copy constructor implementation (java)

For 2 variables, the statements are okay to write in the copy constructor block. But for a situation, in which there are several variables, can please someone help me knowing how similar result can be attained? I trier using this but it turned out to be a final variable.
class Obj
{
int a, b;
Obj(int a, int b)
{this.a = a; this.b =b;}
Obj(Obj obj1)
//trying to copy every variable by concise logic here
//instead of writing for each and every variable
{a = obj1.a; b = obj1.b;}
}
class CopyObj2
{
public static void main(String[] args)
{
Obj obj1 = new Obj(5,10);
System.out.println("Obj1\t"+obj1.a+", "+obj1.b);
Obj obj2 = new Obj(obj1);
System.out.println("Obj2\t"+obj2.a+", "+obj2.b);
}
}
There is no native way to do that - the only way is to assign field values by hand, as you did.
As a helper - you can try to use Orika - Java bean mapping framework (works if your classes are beans).
I tried using this but it turned out to be a final variable.
this is the reference to your object. You can't assign another value to him - it just doesn't make a sense.
The copy constructor is used in java's AWT stemming Point, Rectangle, Polygon and other geometric classes. Typically where there are many objects.
One does not need a copy constructor for immutable classes with final fields.
Experience with mutable classes let me tend to advise switching to immutable classes.
With copy constructors one ends up with much copying or sharing internal data (like arrays or lists). The code style is not that nice.
For completeness:
There is also cloning Object.clone() as alternative to a copy constructor, but it is slowly falling out of favor, because of its overhead.
Then there is serialisation for copying too, which is still heavily in use, but should not be used here.

making a class immutable in java

To make a class immutable what I can do is:
1)Make class final
2)do not provide setters
3)mark all variables as final
But if my class has another object of some other class then , somone can change value of that object
class MyClass{
final int a;
final OtherClass other
MyClass(int a ,OtherClass other){
this.a = a;
this.other = other;
}
int getA(){
return a;
}
OtherClass getOther(){
return other;
}
public static void main(String ags[]){
MyClass m = new Myclass(1,new OtherClass);
Other o = m.getOther();
o.setSomething(xyz) ; //This is the problem ,How to prevent this?
}
}
A) Make the OtherClass immutable as well
or
B) Don't allow direct access to the OtherClass object, instead providing only getters to act as a proxy.
Edit to add: You could make a deep copy of OtherClass and return a copy rather than the original, but that generally isn't the type of behavior you would expect in Java.
Immutability is best considered from the perspective of the API user. So your object API needs to satisfy the following two conditions:
No way for an external user to change the value of the object
A guarantee that any time the user reads or makes use of the object's value in the future, it will get the same result
Important note: It is in fact OK to have mutable data inside an immutable object as long as it behaves as an immutable object from the perspective of the API user. Consider java.lang.String for example: although it is generally considered as the definitive immutable class, it does in fact have a mutable internal field for caching the hashCode (not many people know this!).
So to address your question, if you wish to contain another (mutable) object inside an immutable object then you typically need to do one or more of the following:
Guarantee that nobody else can change the value of the mutable object. Typically this means ensuring that no-one else can have a reference to the mutable object, so this is only usually possible if you create the object yourself rather than accept a reference from outside.
Take a defensive deep copy of the mutable object, and don't hand out references to the new copy. Only allow operations that read the new copy in the public API. If you need to hand out a reference to this object, then you need to take another defensive copy (to avoid handing out a reference to the internal copy).
Use an immutable wrapper for the mutable object. Something like Collections.unmodifiableList. This is useful if you want to hand out a reference to the internal mutable object but don't want to run the risk of it being modified.
All of these solutions are a bit hacky - a better solution overall is to avoid the use of mutable objects within immutable objects. In the long run it's asking for trouble because sooner or later a mutable reference will leak out and you will have an extremely hard to find bug. You are better moving towards a full hierarchy of immutable objects (the approach taken by languages like Scala and Clojure)
I assume OtherClass (by the way you say Other once) is meant to be a class you don't control, or which has to have a setter.
If you can't remove getOther, change it to getOtherView and return a read-only view of other. There will be wrappers for all the get methods, but no set ones.
Return deep clones from your getters. You may find this to be no easy task.
All the objects referenced in the immutable class should be immutable, or at least be encapsulated as private and making sure that they are not modified (not inside the methods of your class and definitely not from the outside). For instance, if you have this situation:
public class MyImmutable {
private MutableClass mutableObject;
}
... You can not provide the getMutableObject() method, because doing so will open the door for outside modifications, like this:
myImmutable.getMutableObject().setSomeAttribute(newValue);
As a special case of the above, all collections and/or maps should be made immutable, with the ummodifiableXXX() methods in the Collections class.
you cannot (reasonably) stop that in java. if you don't have control over the other class, there are ways to effectively get immutable behavior, but it can be very expensive in practice. basically, you must always return a copy of that class in any public method return values. (the jdk actually has this problem with the TimeZone class).
But If my class has another object of some other class then , somone
can change value of that object...
Java objects are not primitive. If you mark a primitive as final, then its value cannot be changed once it is assigned. However, object contents cannot be final, only object references can be final. So you cannot make an object in this way.
One solution might be abandoning all setter/mutator methods those could change the particular fields of the object and encapsulating them in a way that you can only access them, not change them.
It is possible to create the immutable class in java by following ways
1.Don't Provide setter methods.
2.Make all fields are as final and private.
3.Make Class as final.

What is this field-by-field copy done by Object.clone()?

In Effective Java, the author states that:
If a class implements Cloneable,
Object's clone method returns a
field-by-field copy of the object;
otherwise it throws
CloneNotSupportedException.
What I'd like to know is what he means with field-by-field copy. Does it mean that if the class has X bytes in memory, it will just copy that piece of memory? If yes, then can I assume all value types of the original class will be copied to the new object?
class Point implements Cloneable{
private int x;
private int y;
#Override
public Point clone() {
return (Point)super.clone();
}
}
If what Object.clone() does is a field by field copy of the Point class, I'd say that I wouldn't need to explicitly copy fields x and y, being that the code shown above will be more than enough to make a clone of the Point class. That is, the following bit of code is redundant:
#Override
public Point clone() {
Point newObj = (Point)super.clone();
newObj.x = this.x; //redundant
newObj.y = this.y; //redundant
}
Am I right?
I know references of the cloned object will point automatically to where the original object's references pointed to, I'm just not sure what happens specifically with value types. If anyone could state clearly what Object.clone()'s algorithm specification is (in easy language) that'd be great.
Yes, a field by field copy does mean that when it creates the new (cloned) object, the JVM will copy the value of every field from the original object into the cloned object. Unfortunately this does mean that you have a shallow copy. If you desire a deep copy, you can override the clone method.
class Line implements Cloneable {
private Point start;
private Point end;
public Line() {
//Careful: This will not happen for the cloned object
SomeGlobalRegistry.register(this);
}
#Override
public Line clone() {
//calling super.clone is going to create a shallow copy.
//If we want a deep copy, we must clone or instantiate
//the fields ourselves
Line line = (Line)super.clone();
//assuming Point is cloneable. Otherwise we will
//have to instantiate and populate it's fields manually
line.start = this.start.clone();
line.end = this.end.clone;
return line;
}
}
Also one more important thing about the cloning is, the constructor of the cloned object is never invoked (only the fields are copied). So if the constructor initializes an external object, or registers this object with some registry, then that will not happen for the cloned object.
I personally prefer to not use Java's cloning. Instead I usually create my own "duplication" methods.
It means a shallow copy -- the fields are copied, but if you have any references, what these point to is not copied -- you will have two references to the same object, one in the old object and one in the new, cloned object. However, for fields that have primitive types, the field is the data itself, so they get copied regardless.
newObj.x = this.x; //redundant
newObj.y = this.y; //redundant
that's right - these are redundant, since they will have already been copied by Object's clone() method.
Thinking of it as a data copy is correct. Primitive types are copied, and references are also copied so they point to the same object. For example,
class A implements Cloneable {
Object someObject;
}
A a = new A();
a.someObject = new Object();
A cloneA = (A)a.clone();
assert a.someObject==cloneA.someObject;
The default clone performs shallow copy of values. For primitive values, this is enough and no extra work is needed.
For objects, the shallow copy means copying the reference only. Therefore, in these cases a deep copy is usually needed. The exception for this is when the reference points to an immutable object. Immutable objects can't have their apparent state changed, therefore their references can be copied around safely. For example, this applies to String, Integer, Float, enumerations (if not made mutable by mistake).

Categories