How to write a copy constructor in Java – J037

by | Oct 22, 2015

DeegeU Java Course

The “How to write a copy constructor in Java” video is part of a larger free online class called “Free Java Course Online”. You can find more information about this class on “Free Java Course Online” syllabus.

Transcript – How to write a copy constructor in Java

Hi everyone! We’ve covered all kinds of methods to create Java class instances. What if we want to create an instance that’s just like the one over there. We just want a copy. And that’s what we’re covering. The copy constructor in Java, coming up next.

So here’s the situation. We need a copy of an object. We have A, and after copying our object we have a second object that is the same in every way as A, but is not A.

Java copy constructors - Free Java Course Online - DeegeU

We need to clone George to create a second ninja.

One example of why we’d want to do this is, say we have an enemy in a video game. It has a number of hit points, a weapon it’s carrying, a tool belt full of tools, and a name. This baddie has the ability to duplicate itself. So when it duplicates, we need to create a copy of the enemy so there are two, each with their own hit points, own weapon, own tools, etc.

The first thought might be to create a new instance like this.

Ninja george = new Ninja();
Ninja gracie = george;

We have enemy one, and we create enemy two and assign it to the first enemy. Done. This really didn’t work. We just have two enemy variables pointing to the same enemy. This didn’t copy anything, and we still have one instance. We need to create a copy constructor in Java to have a new enemy instance.

A copy constructor is this. It’s a method that takes an instance of a class, and returns a new instance copied exactly like the first class. You can use a static factory method, but best practice is use a constructor that takes a single instance of the class as a parameter. We’ll create our copy constructor to use a constructor.

What goes in our copy constructor? Well the next thought is to create a new enemy object, and copy the attributes over. That looks like this.

public Ninja(Ninja copy) { 
    // create new instance
    Ninja newNinja = new Ninja();
    
    // copy instance values
    newNinja.name = copy.name;
    newNinja.hitPoints = copy.hitPoints;
    newNinja.weapon = copy.weapon;
    newNinja.belt = copy.belt;

    // return copy
    return newNinja;
}

Unfortunately this doesn’t work either. We wanted two enemies, but we really got two enemies sharing a weapon and toolbelt. If we change a value on one weapon, say to overheating, both enemies will experience the change. That’s because we did something called a shallow copy.

It’s interesting to note the hit points and name were not a problem to copy. If we change the hit points on one enemy, the other is not affected. The reason is primitive values are just values. There is no pointer to the value. They are immutable.

What about the name? Strings are classes, so do we have the same problem? If we change the name from George to Gracie, will they both be called Gracie?

Nope. Strings are immutable classes. We can’t change the value, so what would happen is we’d assign the name pointer to a new string object. After copying and changing the name, the enemies’ names would point to different string instances.

To have truly different enemies, we need to do something called a deep copy. That means every class attribute must be copied. And deep really means deep! Remember our tool belt? We can’t just copy arrays of class instances. Every element needs a copy too. Otherwise the belts would point to the same instances.

public Ninja(Ninja copy) { 
    // create new instance
    Ninja newNinja = new Ninja();
    
    // copy instance values
    newNinja.name = copy.name;
    newNinja.hitPoints = copy.hitPoints;
    newNinja.weapon = new Weapon(copy.weapon);
    newNinja.belt = new Belt();
    for (Tool tool: copy.belt) {
       newNinja.belt.append(new Tool(tool)); 
    }

    // return copy
    return newNinja;
}

It gets ugly quick for classes with large attribute trees. However, to have a true copy, that’s what we need to do in our copy constructor. Make a new instance of everything. Best practice is copy constructors provide deep copies.

Some of you are probably thinking there got to be a better way, and digging through the Java API we’d notice, hey, every object has a clone method. The clone method is a copy constructor implemented as a static factory. Kind of. Unfortunately the clone method is a colossally horrible idea.

The way clone works is our object must implement Cloneable in order to be cloned. The reason is the Object class has a clone method that checks to see if the Class implements Cloneable. If it doesn’t, clone must throw an exception. So every time we clone, we need to check for exceptions.

When we clone an object, we really need to call super on the clone method. The reason is we don’t always have access to all the state. Some state might be private, so we need each class in the class hierarchy to handle it’s own part for clone. Another problem is clone is protected. And if any part of our class hierarchy doesn’t implement Cloneable, the whole thing falls apart.

Long story short, too late. There is nothing in Java that provides deep copies for free.

So what do we do? Well if we need a copy constructor, step one is to write our own. This is better because we don’t need to mess with the Cloneable interface and it doesn’t throw exceptions. It’s just alot of work. The advantage of a copy constructor is you have complete control over how it’s implemented, and it returns the class instance you want.

A second thing that will help when making copy constructors is immutable objects. Remember earlier, we had no problems with primitives and strings. If our enemies consisted of immutable objects, copies become very easy. It really depends on what we’re doing, but if we can avoid mutable objects, it will make things easier.

Finally another option is don’t copy anything. Make sure copying is really what you need to do. There’s nothing inherently wrong with copying objects, but we do need to be very careful. If we can avoid it, even better.

Thanks for watching! Copying instances can get very tricky, so if you have any questions let me know in the comments. Make sure you subscribe to the channel, so you don’t miss a video! Liking the video helps me understand what I’m doing right, so if you liked the video… you know what to do.

And with that, I’ll see you in the next tutorial!




Related Posts

Tools Used

  • Java
  • NetBeans

Media Credits

All media created and owned by DJ Spiess unless listed below.

  • Clipart https://openclipart.org/

Music
Just Nasty by Kevin MacLeod is licensed under a Creative Commons Attribution license (https://creativecommons.org/licenses/by/4.0/)
Source: http://incompetech.com/music/royalty-free/?keywords=Just+Nasty
Artist: http://incompetech.com/

Get the code

The source code for “How to write a copy constructor in Java” can be found on Github. If you have Git installed on your system, you can clone the repository by issuing the following command:

 git clone https://github.com/deege/deegeu-java-intro.git

Go to the Support > Getting the Code page for more help.

If you find any errors in the code, feel free to let me know or issue a pull request in Git.

Don't miss another video!

New videos come out every week. Make sure you subscribe!

Comments

comments

DJ Spiess

DJ Spiess

Your personal instructor

My name is DJ Spiess and I’m a developer with a Masters degree in Computer Science working in Colorado, USA. I primarily work with Java server applications. I started programming as a kid in the 1980s, and I’ve programmed professionally since 1996. My main focus are REST APIs, large-scale data, and mobile development. The last six years I’ve worked on large National Science Foundation projects. You can read more about my development experience on my LinkedIn account.

Pin It on Pinterest

Share This