Значение объекта нулевое

Я новичок в Java и пытаюсь реализовать связанный список (я знаю, что для этой цели существует класс списка, но выполнение его с нуля позволяет мне понять, как язык работает внутри)

В основном методе я объявляю 4 узла и инициализирую 3. Головной узел связанного списка имеет значение null. В первый раз, когда функция добавления вызывается с параметрами head и newNode, head имеет значение null, поэтому я инициализирую head и присваиваю ей значение newNode. В основном методе я ожидаю, что головной объект должен иметь новые значения, установленные из метода добавления. Но голова по-прежнему нулевая.

Я был бы признателен за понимание, почему это происходит.

Извините, если код не чистый, большое спасибо!

public class LinkedList
{
    public void add(Node newNode, Node head)
    {
        if(head == null) 
        {
            head = new Node(); 
            head = newNode;              
        }
        else 
        {
            Node temp = new Node(); 
            temp = head; 

            while(temp.next!=null)
            {
                temp = temp.next; 
            }
            temp.next = newNode; 
        }    
    }

    public void traverse(Node head)
    {
        Node temp = new Node(); 
        temp = head; 

        System.out.println("Linked List:: ");

        while(temp.next!=null);  
        {
           System.out.println(" "  + temp.data); 
            temp = temp.next;
        }
    }

    public static void main(String args[])
    {
        Node head = null;
        Node newNode = new Node(null, 5); 
        Node newNode2 = new Node(null, 15); 
        Node newNode3 = new Node(null,30); 

        LinkedList firstList = new LinkedList(); 

        firstList.add(newNode,head); 

       // Part that I don't understand
       // why is head still null here? 

        if(head==null)
        {
         System.out.println("true");
        }

        firstList.traverse(head); 
        firstList.add(newNode2,head); 
        firstList.traverse(head); 
        firstList.add(newNode3,head); 
        firstList.traverse(head); 

    }

}

public class Node
{
    public Node next; 
    public int data; 

    public Node(Node next, int data)
    {
        this.next = next; 
        this.data = data; 
    }

    public Node()
    {
        this.next = null; 
        this.data = 0; 
    }

}

person user1637192    schedule 30.08.2012    source источник
comment
Вы можете найти этот пост интересным. Когда вы пишете head = new Node() в начале своего кода, вы изменяете локальную копию аргумента, но это не меняет его значения в вызывающем коде.   -  person assylias    schedule 31.08.2012
comment
Какие шаги вы предприняли для отладки?   -  person Dave Newton    schedule 31.08.2012


Ответы (4)


Аргументы метода Java передаются по значению.

public void add(Node newNode, Node head)
{
    if(head == null) 
    {
        head = new Node(); 
        head = newNode;              
    }
    ...

Вышеприведенное изменяет только локальную переменную head в области add. Ссылка на локальную переменную head в области видимости main невозможна. Возможно, вам следует вернуть значение, если вы хотите, чтобы вызывающая сторона могла получить новое значение.


Честно говоря, основной принцип объектно-ориентированного программирования заключается в инкапсуляции; head вашего LinkedList в идеале должно быть внутренним полем. Почему это должно быть отдельной частью? Если вы действительно хотите, чтобы head были изолированы, то почему traverse и add не статичны? Вы должны попытаться пересмотреть свой дизайн. Я решил переписать ваш код здесь.

final class List {

  private Node head;

  public void add(final Node node) {
    if (head == null) {
      head = new Node();
    }
    Node cur;
    for (cur = head; cur.next != null; cur = cur.next)
      ;
    cur.next = node;
  }

  public String toString() {
    final StringBuilder builder = new StringBuilder("Linked List::");
    for (Node cur = head.next; cur != null; cur = cur.next) {
      builder.append("\n ").append(cur.data);
    }
    return builder.toString();
  }
}

final class Node {

  int data;
  Node next;

  Node(final int data) {
    this.data = data;
  }

  Node() { }
}

... затем, чтобы проверить:

  private static Node[] nodesFor(final int... values) {
    int n = values.length;
    final Node[] nodes = new Node[n];
    while (n > 0) {
      nodes[--n] = new Node(values[n]);
    }
    return nodes;
  }

  public static void main(final String[] argv) {
    final List list = new List();
    for (final Node node : nodesFor(5, 15, 30)) {
      list.add(node);
      System.out.println(list);
    }
  }
person obataku    schedule 30.08.2012

Я думаю, что проблема внутри функции «добавить». Вы только меняете значение «head» внутри области действия функции, а не за ее пределами. Вы можете найти полезную информацию о том, как Java обрабатывает передаваемые значения параметров здесь< /а>.

Хорошая реализация LinkedList в Java находится здесь.

person songokuhd    schedule 30.08.2012

Создание ссылки "head" на другой узел не влияет на вызывающий код (java передает ссылки, которые в java являются "значениями" адресов).

Вам нужна постоянная ссылка на голову, поэтому сделайте ее полем своего класса:

private Node head = new Node(); // the head of your Node tree

public void add(Node newNode, Node parent) {
    // add node to parent.
    // for some calls, the parent will be the head
}
person Bohemian♦    schedule 30.08.2012
comment
Java передает значения, а не ссылки; дело в том, что в Java вы никогда напрямую не касаетесь значения объекта (как вы могли бы сделать это в C++), а просто храните ссылку на него. - person obataku; 31.08.2012

Вот лучшая имплантация вашего связанного списка. Пожалуйста, обрати внимание:

  1. _head должен быть закрытым членом
  2. Узел — это внутренний механизм. вы должны указать параметр данных для вашего метода добавления вместо объекта Node
  3. Я написал это, просто, но на основе вашего кода, реализации

    public class LinkedList{
    private Node _head;
    public void add(int data)
    {               
            //Understand this code! What happens if _head=null?                 
            _head=new Node(_head,data); 
            /*
                 //Use the following code for a "Normal" nodes-order
                 if(_head==null)
                    _head=new Node(null,data);
                 else{
                   Node temp=_head;
                   while( temp.next!=null)
                      temp=temp.next;            
                   temp.next=new Node(null,data); 
                 }
            */
    }
    public void traverse()
    {
        System.out.println("Linked List:: ");
        Node temp=_head;
        while(temp!=null){
                System.out.println(" "  + temp.data); 
                temp = temp.next;
        }
    }
    public LinkedList(){
        _head=null;         //null is our lists anchor
    }
    
    public static void main(String args[])
    {
        LinkedList firstList = new LinkedList(); 
    
        firstList.add(5); 
        firstList.traverse(); 
        firstList.add(15); 
        firstList.traverse(); 
        firstList.add(30); 
        firstList.traverse(); 
    
    }
    

    }

person Eli Turchinsky    schedule 30.08.2012
comment
Порядок в этом случае является логическим понятием. Это действительно зависит от того, что вы хотите делать со своим кодом. Я отредактирую его, чтобы показать и другой вариант. - person Eli Turchinsky; 31.08.2012