Я получаю исключение нулевого указателя для связанного списка genari c? - PullRequest
0 голосов
/ 24 апреля 2020

Я получаю сообщение об ошибке:

java.lang.NullPointerException
    at ListTest.main(ListTest.java:35)

Это код, о котором идет речь:

a.Replace(a.GetValue()*5);

или

// replaces the value of the current element with the specified value
    // this should not be possible for an empty list
    public void Replace(T data)
    {
      if(!IsEmpty())
      {
          this.curr.setData(data);
      }
    }

или

// accessor and mutator for the data component
    public T getData()
    {
        return data;
    }

    public void setData(T data)
    {
        this.data = data;
    }

Это подходит для genarate и печати нескольких связанных списков, используя genarics. Это полный код:

// the Node class
class Node<T>
{
    public T data;
    private Node link;

    // constructor
    public Node()
    {
        this.data = null;
        this.link = null;
    }

    // accessor and mutator for the data component
    public T getData()
    {
        return data;
    }

    public void setData(T data)
    {
        this.data = data;
    }

    // accessor and mutator for the link component
    public Node getLink()
    {
        return this.link;
    }

    public void setLink(Node link)
    {
        this.link = link;
    }
}

// the List class
public class List<T>
{
    public static final int MAX_SIZE = 50;
    private Node<T> head;
    private Node<T> tail;
    private Node<T> curr;
    private int num_items;


    // constructor
     // remember that an empty list has a "size" of -1 and its "position" is at -1
    public List()
    {
        this.head = null;
        this.tail = null;
        this.curr = null;
        this.num_items = 0;
    }

    // copy constructor
    // clones the list l and sets the last element as the current
    public List(List<T> l)
    {
        Node<T> n = l.head;
        this.head = null;
        this.tail = null;
        this.curr = null;
        this.num_items = 0;

        while(n!= null)
        {
            this.InsertAfter(n.getData());
            n = n.getLink();
        }
    }

    // navigates to the beginning of the list
    public void First()
    {
        this.curr = this.head;
    }

    // navigates to the end of the list
    // the end of the list is at the last valid item in the list
    public void Last()
    {
        this.curr = this.tail;
    }

    // navigates to the specified element (0-index)
    // this should not be possible for an empty list
    // this should not be possible for invalid positions
    public void SetPos(int pos)
    {
        if(!this.IsEmpty() && pos >= 0 && pos < this.num_items)
        {
            this.curr = this.head;
            for(int i = 0; i < pos; i++)
            {
                this.curr = this.curr.getLink();
            }
        }
    }

    // navigates to the previous element
    // this should not be possible for an empty list
    // there should be no wrap-around
    public void Prev()
    {
        if(!this.IsEmpty() && this.curr != this.head)
        {
            Node<T> temp = this.head;
            while(temp.getLink() != this.curr)
            {
                temp = temp.getLink();
            }
            this.curr = temp;
        }
    }

    // navigates to the next element
    // this should not be possible for an empty list
    // there should be no wrap-around
    public void Next()
    {
        if(this.IsEmpty() && this.curr != this.tail)
        {
            this.curr = this.curr.getLink();
        }
    }

    // returns the location of the current element (or -1)
    public int GetPos()
    {
       if(this.IsEmpty())
       {
           return -1;
       }
       Node<T> temp = this.head;
       int i = 0;
       while(temp != this.curr)
       {
           temp = temp.getLink();
           i++;
       }
       return i;
    }

    // returns the value of the current element (or -1)
    public T GetValue()
    {
      if(this.IsEmpty())
      {
          return null;
      }
      else
      {
          return this.curr.getData();
      }
    }

    // returns the size of the list
    // size does not imply capacity
    public int GetSize()
    {
       return num_items;
    }

    // inserts an item before the current element
    // the new element becomes the current
    // this should not be possible for a full list
    public void InsertBefore(T data)
    {
        if(!this.IsFull())
        {
            if(this.IsEmpty())
            {
                this.InsertAfter(data);
            }
            else
            {
                if(this.curr == this.head)
                {
                    this.head = new Node();
                    this.head.setData(data);
                    this.head.setLink(curr);
                    this.curr = this.head;
                }
                else
                {
                    this.Prev();
                    this.InsertAfter(data);
                }
            }
            num_items++;
        }
    }

    // inserts an item after the current element
    // the new element becomes the current
    // this should not be possible for a full list
    public void InsertAfter(T data)
    {
        if(!this.IsFull())
        {
            Node<T> temp = new Node();
            temp.setData(data);
            if(this.IsEmpty())
            {
                this.head = temp;
                this.tail = temp;
                this.curr = temp;
            }
            else
            {
                if(this.curr == this.tail)
                {
                    this.curr.setLink(temp);
                    this.curr = temp;
                    this.curr = tail;
                }
                else
                {
                    temp.setLink(this.curr.getLink());
                    this.curr.setLink(temp);
                    this.curr = temp;
                }
            }
            this.num_items++;
        }
    }

    // removes the current element (collapsing the list)
    // this should not be possible for an empty list
    public void Remove()
    {
      if(!this.IsEmpty())
      {
          if(this.curr == this.head)
          {
              this.head = this.curr.getLink();
              this.curr = this.curr.getLink();
              if (this.head == null)
              {
                  this.tail = null;
              }
          }
          else
          {
              this.Prev();
              this.curr.setLink(this.curr.getLink().getLink());
              if(this.curr.getLink() == null)
              {
                  this.tail = this.curr;
              }
              this.Next();
          }
          this.num_items--;
      }
    }


    // replaces the value of the current element with the specified value
    // this should not be possible for an empty list
    public void Replace(T data)
    {
      if(!IsEmpty())
      {
          this.curr.setData(data);
      }
    }

    // returns if the list is empty
    public boolean IsEmpty()
    {
        return (this.head == null);
    }

    // returns if the list is full
    public boolean IsFull()
    {
        return (this.num_items == MAX_SIZE);
    }

    // returns if two lists are equal (by value)
    public boolean Equals(List l)
    {
        if(this.num_items != l.num_items)
        {
            return false;
        }
        Node<T> a = this.head;
        Node<T> b = l.head;
        while(a != null)
        {
            if(a.getData() != b.getData())
            {
                return false;
            }
            a = a.getLink();
            b = b.getLink();
        }
        return true;
    }

    // returns the concatenation of two lists
    // l should not be modified
    // l should be concatenated to the end of *this
    // the returned list should not exceed MAX_SIZE elements
    // the last element of the new list is the current
    public List Add(List l)
    {
        List<T> t = new List(this);
        Node<T> temp = l.head;
        while (temp != null)
        {
            t.InsertAfter(temp.getData());
            temp = temp.getLink();
        }
        return t;
    }

    // returns a string representation of the entire list (e.g., 1 2 3 4 5)
    // the string "NULL" should be returned for an empty list
    public String toString()
    {
        if(this.head == null)
        {
            return "NULL";
        }
        else
        {
            String s = "";
            Node<T> temp = this.head;
            while(temp != null)
            {
               s += temp.getData() + " ";
               temp = temp.getLink();
            }   
            return s;
        }
    }
}

Основной:

public class ListTest
{
    public static void main(String[] args)
    {
        List<Integer> a = new List<Integer>();
        List<Integer> b = new List<Integer>();

        System.out.println(" 1 " + a.GetValue());
        System.out.println(" 2 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println(" 3 b(" + b.GetSize() + "/" + b.GetPos() + ") = " + b);
        for (int i=1; i<=25; i++)
        {
            a.InsertAfter(i);
            b.InsertBefore(i);
        }
        System.out.println(" 4 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println(" 5 b(" + b.GetSize() + "/" + b.GetPos() + ") = " + b);
        List<Integer> c = new List<Integer>(a);
        System.out.println(" 6 c(" + c.GetSize() + "/" + c.GetPos() + ") = " + c);
        a.Remove();
        a.Remove();
        for (int i=0; i<5; i++)
            a.Prev();
        a.Remove();
        a.Remove();
        System.out.println(" 7 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        a.First();
        a.Remove();
        for (int i=0; i<a.GetSize()/2; a.Next(),i++)
        {
            a.Replace(a.GetValue()*5);
            a.Next();
        }
        System.out.println(" 8 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        a.Last();
        a.Next();
        a.Next();
        a.Remove();
        System.out.println(" 9 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        a.SetPos(a.GetSize()*2/3);
        a.Replace(a.GetValue()*12345);
        System.out.println("10 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        a.SetPos(a.GetSize());
        a.Remove();
        System.out.println("11 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        a.SetPos(a.GetSize()-1);
        a.Remove();
        System.out.println("12 a is " + (!a.IsEmpty() ? "not " : "") + "empty");
        System.out.println("13 a is " + (!a.IsFull() ? "not " : "") + "full");
        for (int i=0; i<1000; i++)
            a.InsertBefore(i);
        System.out.println("14 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println("15 c(" + c.GetSize() + "/" + c.GetPos() + ") = " + c);
        System.out.println("16 a is " + (!a.IsEmpty() ? "not " : "") + "empty");
        System.out.println("17 a is " + (!a.IsFull() ? "not " : "") + "full");
        List<Integer> d = new List<Integer>(a);
        System.out.println("18 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println("19 d(" + d.GetSize() + "/" + d.GetPos() + ") = " + d);
        System.out.println("20 a " + (a.Equals(d) ? "==" : "!=") + " d");
        a.Remove();
        System.out.println("21 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println("22 d(" + d.GetSize() + "/" + d.GetPos() + ") = " + d);
        System.out.println("23 a " + (a.Equals(d) ? "==" : "!=") + " d");
        a = new List<Integer>(c);
        c.Remove();
        System.out.println("24 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println("25 b(" + b.GetSize() + "/" + b.GetPos() + ") = " + b);
        System.out.println("26 c(" + c.GetSize() + "/" + c.GetPos() + ") = " + c);
        System.out.println("27 a " + (a.Equals(c) ? "==" : "!=") + " c");
        List<Integer> e = b.Add(a);
        System.out.println("28 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println("29 b(" + b.GetSize() + "/" + b.GetPos() + ") = " + b);
        System.out.println("30 e(" + e.GetSize() + "/" + e.GetPos() + ") = " + e);
        for (int i=0; i<1000; i++)
        {
            b.Remove();
            c.Remove();
        }
        System.out.println("31 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println("32 b(" + b.GetSize() + "/" + b.GetPos() + ") = " + b);
        System.out.println("33 c(" + c.GetSize() + "/" + c.GetPos() + ") = " + c);
        System.out.println("34 e(" + e.GetSize() + "/" + e.GetPos() + ") = " + e);
        List<Integer> f = b.Add(a);
        System.out.println("35 a(" + a.GetSize() + "/" + a.GetPos() + ") = " + a);
        System.out.println("36 b(" + b.GetSize() + "/" + b.GetPos() + ") = " + b);
        System.out.println("37 f(" + f.GetSize() + "/" + f.GetPos() + ") = " + f);

        List<Character> g = new List<Character>();
        for (char i='a'; i<='m'; i++)
        {
            g.InsertAfter(i);
            g.InsertBefore((char)(i+13));
        }
        System.out.println("38 g(" + g.GetSize() + "/" + g.GetPos() + ") = " + g);

        List<Float> h = new List<Float>();
        for (float i=2.71828f; i<=3.14159f; i+=.111f)
            h.InsertAfter(i);
        h.InsertBefore(3.14159f);
        System.out.println("39 h(" + h.GetSize() + "/" + h.GetPos() + ") = " + h);
    }
}

1 Ответ

1 голос
/ 24 апреля 2020

Глядя на ваш код. Похоже, в списке «а» у вас было 2 элемента, а «Удалить» вызывалось более 2 раз. Это оставило бы указатель «head» списка на ноль.

Причиной root вашего NPE здесь является a.GetValue () * 5

Когда все элементы удаляются из «a», тогда GetValue возвращает «ноль» (обычно это не так хорошая практика). Затем выражение оценивается как «null * 5), и это вызывает NPE в вашем случае.

Надеюсь, это поможет, и ответ был вовремя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...