Does anyone have a good way of creating a copy of a class?

Ok, this is really bugging me: Java wont create a copy of a class

What i have is a HashMap of all of my template objects - bullets, ships, asteroids, planets, images, sounds, etc. Now, using Slick2D Images i can use the duplicate method tog et a copy of my stored template.

How can i write a similar duplicate() method for my other classes?

I’ve been working on this all day with no luck:
Simply implementing Clonable and writing a public clone() override fails.
Creating a duplicate() class that creates a new object and then sets all its feilds and properties = to the original class fails.
Constructors that use an object to initialize a new object fails.

Seriously, what do i have to do to copy a class?
(I may be being a tard amd making a prtoblem where there is none, please put me streight if so!)

Chears,
Matt

what do you mean clone,duplicate,contructors fail?

Is it something like:

MyClass b = a.clone(); or a.duplicate(); or new MyClass(a);

then a == b fails?

try to override equals() (and maybe hashcode as well),
I think you’ll find the problem there…

what seems to be happening is the the class I’ve copied, however i do it, is only a reference to the origional class, not a new class.

so if i clone 10 particle effects from the ‘explosion’ stored class, what i get is 10 copies that update 10* faster - where the update is repeatedly called on the stored class. The same thing seems to happen for other classes too.

I was wondering if there is a way of cloning any arbitrary class and retaining to references to the original.

what I’m really looking for is pointers on how to go about creating a Duplicator class with something like a


public static Object Duplicate(Object origional)
{
    ** Magic!**
    return copyOfOrigional;
}

You have to perform a deep copy yourself.


public class MyClass implements Cloneable {
  Arraylist<MyShip> listOfThings;
  int location;
  String name;

  public MyClass() {
    listOfThings = new ArrayList<MyShip>();
  }

  public Object clone() {
    MyClass result = new MyClass();
    result.location = location;
    result.name = name;
    for(MyShip ship:listOfThings) {
      result.listOfThings.add(ship.clone());
    }
  }
}

Each class that you create that you want to be able to clone you have to implement the clone method and perform a deep copy in there as well.

Brilliant, I think that you may have shed some light on this for me - my Vector2D and Sprite classes do not have a public clone() method :slight_smile:

I think this may be the problem - I am getting a copy of the Ship class, but it retains a reference to the Vector2D and Sprite classes from the original.

Going to have a check to see if that’s the case now. Will keep you posted.

Edit:
Ok, thanks CaptainJester, that did the trick.

I’ve still got some weird bugs going on, but i think they’re now a problem with my Sprite drawing code that i just cant find. Duplication is working fine though, as far as i can tell.

EditEdit:
Got it. I had missed adding a new parent Entity reference to my rendering component. derp.

Thanks again all.

I personally stay away from the clone() function because it does a shallow copy by default (therefore being mostly useless) and otherwise it returns an Object rather than whatever I might want.

Instead, I usually make a constructor that takes the same class as a single parameter.


public class MyClassA
{
    private MyClassB classB;
    private MyClassC classC;
    private ArrayList<ClassD> classDs;

    public MyClassA(MyClassA copy)
    {
        classB = new classB(copy.getClassB());
        classC = new classC(copy.getClassC());
        classDs = new ArrayList<ClassD>();
        for (int i = 0; i < copy.getClassDs().size(); i++)
        {
            classDs.add(new ClassD(copy.getClassDs().get(i)));
        }
    }
}

It’s not very efficient, but it creates a deep copy of your object:

    /**
     * Returns a copy of the object, or null if the object cannot
     * be serialized.
     */
    public static Object copy(Object orig) {
        Object obj = null;
        try {
            // Write the object out to a byte array
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(bos);
            out.writeObject(orig);
            out.flush();
            out.close();

            // Make an input stream from the byte array and read
            // a copy of the object back in.
            ObjectInputStream in = new ObjectInputStream(
                new ByteArrayInputStream(bos.toByteArray()));
            obj = in.readObject();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        catch(ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
        return obj;
    }

I think you could also use BeanUtils.cloneObject(…) from Apache Commons.

I dunno if it makes a shallow clone like BeanUtilsBean.cloneObject(…)

I have used it in the past, but I don’t remember.

You could use Kryo to round trip your objects. You go objects -> bytes -> objects and the second set of objects you get are your copies. Same as kingaschi’s suggestion, but more efficient.

The clone method probably works for your simple case, but requires you to write manual deep copy code and in general sucks. You could extend a Cloneable class and not override clone in your subclass. Also, clone uses an extralinguistic mechanism to create an object without calling a constructor, which is hacky.

A copy constructor sucks when you want to create a copy and you don’t know the class.

There is also Java deep-cloning Library, a library for that purpose only. It looks just what you need.

It sounds like you’re using the ‘prototype’ pattern to define game entity types / configs, so I’d like to humbly suggest using Rebirth as this is exactly the kind of thing that it’s designed to handle.

You can then specify not just the actual class/type in the data but also the parameters for any given template, and as a bonus you can make changes to your data files and see them reflected in your game without needing a restart. If you give an example of how you’re defining and using your template classes/objects I could show you how it would translate.

deep copy or shallow copy? Most of the time you need some mixture. Deep copy libs etc can use a huge amount of memory really fast, because a large part of the object tree is copied “bit for bit” when perhaps a reference will do.

Generally you have to think through the ramifications of new instance vers reference for each field. I tend to have a copy constructor in my classed that need it and use that (work up the class hierarchy too). But it is very class specific as it needs to be (Its like this is all langs, some default which is rarely what you want).