-1

I'm having a lot of difficulty with my stack copy constructor. DSStack extends a Stack abstract class and uses a doubly-linked-list to store data (tokens). It keeps failing (NullPointerException) at the line this.push(oldListNode.getToken()); in the constructor. I've included the methods/classes I think will help with solving my problem. It needs to be a deep copy. Any help or guidance would be awesome.

public class DSStack extends Stack {

    // The list containing the data
    private DSList theStack;

    // Constuct an empty stack using a LinkedList as the container
    public DSStack() {
        theStack = new DSList();
    }

    public DSStack(DSStack other) {
    // Create a reference for the stack to be copied
    Node oldListNode = other.theStack.head;

    while (oldListNode != null) {
        this.push(oldListNode.getToken());
        oldListNode = oldListNode.next;
        }
    }

    /**
     * Adds the given object to the top of the Stack. 
     * @return The given object. 
     */
    public Token push(Token obj) {      
        theStack.add(obj);
        return obj;
    }
}

public class DSList implements List {

    /**
     * Appends the specified element to the end of this list.
     * @param obj The object to add. 
     * @return True if the object has been added to the list. 
     * 
     * @throws NullPointerException if the specified object is null.
     */
    public boolean add(Token obj) {
        if (obj == null) {
            throw new NullPointerException();
        }
        // If list is empty, add new node to front.
        if(isEmpty()) {  
            // Create a new Node. Add Token obj as data
            Node newNode = new Node(null, null, obj);  
            // point head to new Node, newNode
            head = newNode;
            return true;
        } else { 
            // create a reference of the start position in the list
            Node current = head;
            // While there are nodes remaining in the list, advance through to reach the end.
            while (current.next != null) 
                current = current.next;
            // Create a new node and append it to the end of the list, with 'prev' pointing to current (2nd to last node)
            Node newNode = new Node(null, current, obj);
            // Point 2nd to last element to the newest , last node in the list (in next variable)
            current.next = newNode;
            // Return true if successful addition of node.
            return true;
        }
    }
 }

public class Node {

    public Node next;
    public Node prev;

    // data being stored in each node
    private Token t;

    // Node constructor
    public Node(Node next, Node prev, Token token) {
        this.next = next;
        this.prev = prev;
        this.t = token;
    }

    public Token getToken() {
        return t;
    }
}

public class Token {

    public enum Type { OPERATOR, OPERAND, PAREN };
    public Type type;

    private String operator;
    private double operand;

    public Token(double result) {
        this.operand = result;
        this.type = Type.OPERAND;
    }

    public Token(String op) {
        this.operator = op;
        this.type = Type.OPERATOR;

        if ( this.operator.equals("(") || this.operator.equals(")") ) {
            this.type = Type.PAREN;
        }
    }

    public Token(Token other) {
        this.operator = other.operator;
        this.operand = other.operand;
        this.type = other.type;
    }
}
BobSacamano
  • 157
  • 1
  • 8
  • Assuming the answer is correct, it means there was more to the stack trace than you were telling us (the exception was coming, not from the copy constructor directly, but from `push`.) It's a lot easier for us to see what's going on if you include information like that. – D M Apr 06 '17 at 16:22

2 Answers2

1

You have to initialize theStack inside your paramterized constructor public DSStack(DSStack other). I didn't see that happened, hence it still contains null value for any object constructed using your parameterized constructor. Notice that I am talking about the theStack reference in your push method

Yohannes Gebremariam
  • 2,225
  • 3
  • 17
  • 23
0

Writing Constructors could be work of art sometimes. All you have to do

public DSStack()
{
    theStack = new DSList();
}

public DSStack( DSStack other )
{
    this();
    // Rest of the code goes on 
    // Create a reference for the stack to be copied
    Node oldListNode = other.theStack.head;

    while (oldListNode != null) 
    {
        this.push(oldListNode.getToken());
        oldListNode = oldListNode.next;
    }

}

This will make sure that you always initialize theStack variable no matter which constructor you initialized to allocate memory for DSStack object. this() statement actually calls the no-arg constructor where you initialized theStack variable

ShayHaned
  • 358
  • 3
  • 8