class
Copy Constructor example
This is an example of how to create a copy constructor in a class. We have set the example, in order to demonstrate the copy constructor and its use between classes and their subclasses following the steps below:
- We have created
FruitQualities
class,Seed
class andFruit
class, that all have copy constructor. - We have also created
Tomato
class, that extendsFruit
,ZebraQualities
class that extendsFruitQualities
, andGreenZebra
class that extendsTomato
. All subclasses call their super classes’ copy constructors in their copy constructors. - We create a new instance of
Tomato
, that is tomato. - We call
ripenFunc(Tomato t)
, using the tomato, where we use its copy constructor to create another new instance. We get the name of the class of the object created, usinggetClass()
andgetName()
API methods of Class. The object created belongs toTomato
class. - We call
sliceFunc(Fruit f)
, using the tomato. This method creates a newFruit
instance, using the copy constructor. The object created belongs toFruit
class. - We call
ripenFunc2(Tomato t)
, using the tomato, where we get the Constructor of the object, using its class name, withgetClass()
API method and using its constructor, withgetConstructor()
API method of Class. Then we use thenewInstance(Object... initargs)
API method of Constructor to get a new instance of the object. The object belongs toTomato
class. - We call
sliceFunc2(Fruit f)
, using the tomato, that does the same steps asripenFunc2(Tomato t)
does, with aFruit
f as parameter. The object created belongs toTomato
class. - We follow the same steps, creating an instance of
GreenZebra
, that extends theTomato
class. The results from the two first methods are, first aTomato
object, then aFruit
object, whereas in the last two methods aGreenZebra
object is created.
Let’s take a look at the code snippet that follows:
package com.javacodegeeks.snippets.core; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; class FruitQualities { private int w; private int c; private int firmval; private int ripen; private int sml; // etc. public FruitQualities() { // Default constructor // Do something meaningful... } // Other constructors: // ... // Copy constructor: public FruitQualities(FruitQualities frq) { w = frq.w; c = frq.c; firmval = frq.firmval; ripen = frq.ripen; sml = frq.sml; // etc. } } class Seed { // Members... public Seed() { /* * Default constructor */ } public Seed(Seed s) { /* * Copy constructor */ } } class Fruit { private FruitQualities fq; private int seedamnt; private Seed[] s; public Fruit(FruitQualities q, int seedCount) { fq = q; seedamnt = seedCount; s = new Seed[seedamnt]; for (int i = 0; i < seedamnt; i++) { s[i] = new Seed(); } } // Other constructors: // ... // Copy constructor: public Fruit(Fruit f) { fq = new FruitQualities(f.fq); seedamnt = f.seedamnt; s = new Seed[seedamnt]; // Call all Seed copy-constructors: for (int i = 0; i < seedamnt; i++) { s[i] = new Seed(f.s[i]); } // Other copy-construction activities... } // To allow derived constructors (or other // methods) to put in different qualities: protected void addQualities(FruitQualities q) { fq = q; } protected FruitQualities getQualities() { return fq; } } class Tomato extends Fruit { public Tomato() { super(new FruitQualities(), 100); } public Tomato(Tomato t) { // Copy-constructor super(t); // Upcast for base copy-constructor // Other copy-construction activities... } } class ZebraQualities extends FruitQualities { private int stripedness; public ZebraQualities() { // Default constructor super(); // do something meaningful... } public ZebraQualities(ZebraQualities z) { super(z); stripedness = z.stripedness; } } class GreenZebra extends Tomato { public GreenZebra() { addQualities(new ZebraQualities()); } public GreenZebra(GreenZebra g) { super(g); // Calls Tomato(Tomato) // Restore the right qualities: addQualities(new ZebraQualities()); } public void evaluate() { ZebraQualities zq = (ZebraQualities) getQualities(); // Do something with the qualities // ... } } public class CopyConstructor { public static void main(String[] args) { Tomato tomato = new Tomato(); ripenFunc(tomato); // OK sliceFunc(tomato); // OOPS! ripenFunc2(tomato); // OK sliceFunc2(tomato); // OK GreenZebra g = new GreenZebra(); ripenFunc(g); // OOPS! sliceFunc(g); // OOPS! ripenFunc2(g); // OK sliceFunc2(g); // OK g.evaluate(); } public static void ripenFunc(Tomato t) { // Use the "copy constructor": t = new Tomato(t); System.out.println("In ripen, t is a " + t.getClass().getName()); } public static void sliceFunc(Fruit f) { f = new Fruit(f); // Hmmm... will this work? System.out.println("In slice, f is a " + f.getClass().getName()); } public static void ripenFunc2(Tomato t) { try { Class c = t.getClass(); // Use the "copy constructor": Constructor ct = c.getConstructor(new Class[]{c}); Object obj = ct.newInstance(new Object[]{t}); System.out.println("In ripen2, t is a " + obj.getClass().getName()); } catch (Exception e) { System.out.println(e); } } public static void sliceFunc2(Fruit f) { try { Class c = f.getClass(); Constructor ct = c.getConstructor(new Class[]{c}); Object obj = ct.newInstance(new Object[]{f}); System.out.println("In slice2, f is a " + obj.getClass().getName()); } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { System.out.println(e); } } }
Output:
In ripenFunc, t is a methodoverloading.Tomato
In sliceFunc, f is a methodoverloading.Fruit
In ripenFunc2, t is a methodoverloading.Tomato
In sliceFunc2, f is a methodoverloading.Tomato
In ripenFunc, t is a methodoverloading.Tomato
In sliceFunc, f is a methodoverloading.Fruit
In ripenFunc2, t is a methodoverloading.GreenZebra
In sliceFunc2, f is a methodoverloading.GreenZebra
This was an example of how to create and use copy constructors in Java.