2

Can any of you offer help with my implementation of the clone method in the following toy classes? I've read through java documentation and essential java textbook and followed the instructions to no avail.

The problem arises when I try to use the child-class clone method to do a deep copy of the child-class's mutable parent-class field.

When, as per textbooks, I attempt a deep copy of the mutable field using the code line in child-class clone method

Copy.stockItem =  (StockItem) stockItem.clone()

whilst it compiles fine, I get a null pointer exception thrown when I try to clone an instance of a child-class object. The message says

Exception in thread "main" java.lang.NullPointerException: Cannot invoke 
"package.StockItem.clone()" because "this.stockItem" is null
at package.PricedItem.clone(PricedItem.java:25)
at package.CloneMethodDemo.main(CloneMethodDemo.java:10)

When I remove the offending line of code, however, both class methods work fine with no privacy leaks. Can you help me understand what is going wrong?

Thank you.

See below for all relevant code:

Parent class code

public class StockItem implements Cloneable {
    private int number;
    private String name;
    // code for constructor and setters/getters etc.
    
    //CLONE METHOD which works fine
    @Override
    public StockItem clone() throws CloneNotSupportedException{
        try{
            StockItem copy = (StockItem) super.clone();
            return copy;
           }
        catch(CloneNotSupportedException e)
            {
                return null;
            }

Child class

public class PricedItem extends StockItem  implements Cloneable{
    private StockItem stockItem;
    private double price;

    //constructers/setters/getters etc.

    //CLONE METHOD WITH PROBLEM CODE HIGHLIGHTED WITH **
    @Override
    public PricedItem clone() throws CloneNotSupportedException{
        try {
            PricedItem Copy = (PricedItem) super.clone();
            **Copy.stockItem =  (StockItem) stockItem.clone();**
            return Copy;
            }


    }

// test code from external programme file
    StockItem StockItem1 = new StockItem(5, "Seamus");
    StockItem StockItem2 = StockItem1.clone();
    PricedItem PricedItem1 = new PricedItem(StockItem1, 20.99);
    PricedItem PricedItem2 = PricedItem1.clone();

1 Answers1

1

First things first: Welcome to StackOverflow :D

Your Problem

On the line throwing the error, you are trying to call clone() on the class-variable stockItem. However, since you haven't initialized it with any value somewhere in your code, it remains null and you can not invoke methods from null-objects.

Solution

Try to initialize it with some value. It would be best to define some defaults (f.e. a StockItem with number -1 and name "weird" could be considered a default) or just look out at the rest of your code to initialise it properly (we can not see the entire code)

General Recommendations

  • You don't need the cast in the problematic line, since the return value of clone already is StockItem
  • Since StockItem implements Clonable, then every class extending it doesn't have to implement it as well. That is why inheritance was introduced

I hope this helps resolve your problem. Feel free to discuss other issues that may come up due to these changes :D

Kristi
  • 27
  • 7
  • Thanks for the reply. When you say I have to initialise the stockItem parameter before cloning, do you mean in the source file? If so, I would have thought that if I set a default value in the PricedItem clone method then that would make all clone attempts have the same value for the stockItem parameter. – UnknownUser99 Jan 09 '22 at 15:04
  • At the bottom of the code in the question above I added an example of the code I was using that threw the exception I thought that the PricedItem clone method call in the 4th line would have a value for the stockItem parameter as its been initialised in the constructor for PricedItem1; despite this, the clone method throws null. – UnknownUser99 Jan 09 '22 at 15:14
  • Finally, regarding you general recommendations; I thought that the call to super.clone() in the overridden methods went all the way back to the Object clone method and would return an object of Object type. Is this not the case? And, would I not need to create a clone method in the child class as it will be cloning additional fields than its super class's clone method? Thanks again. – UnknownUser99 Jan 09 '22 at 15:19