Search code examples
javaiteratordeque

Why am I getting a null pointer exception in my iterator?


When calling my iterator over a doubly linked list, I am getting a null pointer exception. The null pointer exception occurs in main at line assertEquals(i, (int) it.next());

     /***************************
      * nested class DequeIterator
      ***************************/
     private class DequeIterator implements Iterator<E>
      {
        // instance data member of ListIterator
        private Node current;

        // constructors for ListIterator
        public DequeIterator()
        {
          current = first; // head in the enclosing list
        }

        public boolean hasNext()
        {
          return current != null;
        }

        public E next()
        {
          if (hasNext() == false){ throw new NoSuchElementException();}
          else {
          E ret = current.item;
          current = current.next;
          return ret;
          }
        }

public void addLast(E item) {

        if (item.equals(null)) { throw new NullPointerException(); }

        else {

        Node node = new Node(item, null);
        Node ptr = last;

        ptr.prev.next = node;
        node.next = ptr;
        node.prev = ptr.prev;
        ptr.prev = node;    
        N++;

        }
    }

public static void main(String[] args) {

        Deque<Integer> lst = new Deque<Integer>(); // empty list


        for(int i = 1; i <= 5; i++) {
              lst.addLast(i);
            }
        assertEquals(5, lst.size());
        Iterator<Integer> it = lst.iterator();
        int i = 1;
        while(it.hasNext()) {
          assertEquals(i, (int) it.next());
          i++;
        }
        assertEquals(6, i);
        assertEquals(5, lst.size());
}

Can anybody tell me why I am getting a null pointer exception at that point?


Solution

  • Start off by looking at the termination condition for the loop:

    public boolean hasNext(){
        return current != null;
    }
    

    This means that the last time it runs, it will return null, since it only checks that the current element, not the next element, is non-null.

    So your code becomes something like this:

    Integer it_next = null;
    assertEquals(i, (int)it_next);
    

    And that cast to int is what's throwing the exception. If you look at the rules for how unboxing works, you can figure out why:

    If r is a reference of type Integer, then unboxing conversion converts r into r.intValue()

    So your code becomes similar to

    ((Integer)null).intValue();
    

    which is a method call on a null value, causing the exception.

    Presumably, the fix you want for this is to not return true in hasNext if the next value is null. Something like this:

    public boolean hasNext(){
        return current != null && current.next != null;
    }