Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (107)
games submitted by our members
Games in WIP (535)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  How to make a copy of an object and not just it´s reference?  (Read 1493 times)
0 Members and 1 Guest are viewing this topic.
Offline Axeman

Senior Member


Medals: 7



« Posted 2012-04-26 13:28:31 »

I have a Vector class that basically takes <x, y> coordinates and a lot of vector manipulation methods. Last night I tried to copy a vector called ”force” from ”object1” to ”object2”. Like this:

object2.force = object1.force;

That´s  when I realized that I didn´t create a new, independent, copy. I just copied the reference to object1.force. This basically meant that both object1 and object2 was using the same force-vector. It looked kinda funny, but isn´t what I wanted. Smiley

Now, what do I do to be certain that I create a replica of object1.force, with the same values but an unique reference? I really want to be able to avoid these kind of errors in the future.

Thank you!
Offline Z-Man
« Reply #1 - Posted 2012-04-26 13:41:00 »

This occurs because in Java objects are really just "pointers" to wherever the actual object is stored in memory. So when you set one objectA equal to objectB your really just pointing objectA at the same memory location as objectB. To fix this you need to make a copy of the object, depending on the implementation of the class your using you can do this:
1  
2  
// assuming that force is an object
object2.force = object1.force.clone();


This should (depending on the implementation) mean:
1  
2  
3  
object1.force == object2.force                       // false
object1.force.getClass() == object2.force.getClass() // true
object1.force.equals(object2.force)                  // true


See the API docs about clone() for more info
Offline 65K
« Reply #2 - Posted 2012-04-26 13:43:10 »

Beware that clone() does not create a deep copy.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Axeman

Senior Member


Medals: 7



« Reply #3 - Posted 2012-04-26 13:57:58 »

See if I get it right: clone() creates a new copy of an object, but keeps the same references to the variables inside the object? So in my case, i would create a new Vector, but keep the same references to x and y?

If I want a completly independent object, should I just write my own copy-method in my classes? Is it the easiest/best way to do it?
Offline Z-Man
« Reply #4 - Posted 2012-04-26 14:01:08 »

clone() (should) create a complete new object with the same (but independent) values. So object1's (x,y) wouldn't be affected if you changed object2's (x,y).
Offline Axeman

Senior Member


Medals: 7



« Reply #5 - Posted 2012-04-26 14:10:39 »

Ok, Z-Man. I'll Give it a try asap. Smiley Thank you, guys.
Offline 65K
« Reply #6 - Posted 2012-04-26 14:11:43 »

If x and y are base on primitive types, default cloning is sufficient. Only if your vector class holds references to other objects, you have to take care of them by yourself, by cloning them as well, for example.

Or add some kind of a copy constructor: Vector(Vector sourceVector)

Offline sproingie

JGO Kernel


Medals: 202



« Reply #7 - Posted 2012-04-26 18:28:07 »

Normally I warn people away from using clone, but a pure value type like Vector is a good candidate for being cloneable.  Most of the time though it's better to do what 65K mentioned and use a copy constructor of some sort.
Offline joeyismusic

Junior Member





« Reply #8 - Posted 2012-04-26 19:59:08 »

I just make a getCopy() function in the class, if you want a true copy (you will need a "new" somewhere!).

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
public class something {
    float x = 0;
    float y = 0;

    public something(float x, float y) {
        this.x = x;
        this.y = y;
    }
    public something getCopy() {
        something s = new something(this.x, this.y);
        //set additional values / variables here
       //this is where you "control" the copy / clone logic
       return s;
    }
}
Offline _Al3x

Senior Member


Medals: 7


Indie Games FTW!


« Reply #9 - Posted 2012-04-26 22:03:45 »

I approve joeyismusic way Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Danny02
« Reply #10 - Posted 2012-04-27 11:02:03 »

arg just use the clone method and don't create a new name for it.
Thats what its there for, you can also use the clonable interface so everybody using your class knows that he can savly clone it
Offline Z-Man
« Reply #11 - Posted 2012-04-28 03:15:14 »

arg just use the clone method and don't create a new name for it.
Thats what its there for, you can also use the clonable interface so everybody using your class knows that he can savly clone it
If your going to go the route that joeyismusic suggested, definitely override clone() and implement Cloneable. I was suggesting the clone() method based on the assumption that the OP was trying to copy a class he didn't write. If your trying to copy a class you did write I would definitely implement your own clone() so you have control over what gets copied, and how it's copied.
Offline Nate

JGO Kernel


Medals: 145
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #12 - Posted 2012-04-28 07:44:54 »

This thread makes me realize that Kryo has just about all the information it needs to implement automatic deep copy. In Kryo, serializers are registered for types, so that it knows how to serialize and deserialize various types as they are encountered in an object graph. With just a new method or two, the serializers could know how to do a deep copy. This would be a real deep copy too, not object->bytes->object (which is currently possible, but not efficient). This would be pretty slick as lots of stuff gets reused: the class to serializer registration, walking the object graph, creating new instances of objects via ReflectASM/reflection/Objenesis, using ReflectASM/reflection to access fields and methods, etc.

I've implemented most of it, I'll post tomorrow when it is finished and committed. Works like this...

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
Kryo kryo = new Kryo();
ArrayList test = new ArrayList();
test.add("one");
test.add("two");
test.add("three");
ArrayList test2 = kryo.copy(test);
assertTrue(test != test2);
assertEquals(test, test2);

ArrayList test3 = new ArrayList();
test3.add(1);
test3.add(2f);
test3.add(3d);
test3.add((byte)4);
test3.add((short)5);
test.add(test3);
test2 = kryo.copy(test);
assertTrue(test != test2);
assertEquals(test, test2);


There is also Kryo#copyShallow(Object). Smiley Supporting deep copy for a type is easy, eg here is what I had to add to CollectionSerializer...

1  
2  
3  
4  
5  
6  
7  
8  
public Collection createCopy (Kryo kryo, Collection original) {
   return kryo.newInstance(original.getClass());
}

public void copy (Kryo kryo, Collection original, Collection copy) {
   for (Object element : original)
      copy.add(kryo.copy(element));
}


Just like for deserialization, I have to separate create from copying nested objects in order to have the framework automatically handle multiple references to the same object / circular references.

Sorry for the thread hijack. Cheesy

Offline Nate

JGO Kernel


Medals: 145
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #13 - Posted 2012-04-28 20:39:38 »

Alright, Kryo now supports deep and shallow copying. Cheesy

https://code.google.com/p/kryo/#Copying/cloning

It is implemented for all provided serializers, which covers maps, collections, arrays (any type and number of dimensions), etc. By default FieldSerializer does the copying for POJOs and most user classes, so it is directly assigning from field to field. Kryo can be configured various ways, eg you can use BeanSerializer and then it will do the copying from bean getter to setter. It uses ReflectASM when possible for object creation, field access, and method access. I haven't benchmarked it, but I imagine it is very fast. I added a copy test in the roundTrip method that is used for almost all the unit tests, so the copy functionality has good test coverage.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

E.R. Fleming (16 views)
2014-07-29 03:07:13

E.R. Fleming (5 views)
2014-07-29 03:06:25

pw (39 views)
2014-07-24 01:59:36

Riven (39 views)
2014-07-23 21:16:32

Riven (26 views)
2014-07-23 21:07:15

Riven (28 views)
2014-07-23 20:56:16

ctomni231 (59 views)
2014-07-18 06:55:21

Zero Volt (50 views)
2014-07-17 23:47:54

danieldean (42 views)
2014-07-17 23:41:23

MustardPeter (44 views)
2014-07-16 23:30:00
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!