2012-08-30 85 views
0

我是新来的Java和我试图实现一个链表(我知道一个列表类存在这个目的,但从头开始让我理解语言如何在内部工作)对象值null

在主要方法中,我声明4个节点并初始化3.链接列表的头节点设置为空。 第一次使用参数head和newNode调用add函数时,head为null,所以我初始化head并为它指定newNode的值。 在主要方法中,我期望头对象应该有从add方法设置的新值。但头仍然是空的。

我很感激为什么会发生这种情况。

道歉,如果代码不干净,谢谢大量!

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; 
    } 

} 
+1

您可能会发现[这篇文章](http://stackoverflow.com/questions/40480/is-java-pass-by-reference)有趣。当您在代码的顶部写入'head = new Node()'时,您将更改参数的本地副本,但不会更改其在调用代码中的值。 – assylias

+0

你采取了哪些步骤进行调试? –

回答

2

Java方法参数是按值传递的。

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

上面仅修改在add范围局部变量head。对main范围内的局部变量head的引用是不可能的。也许你应该返回值,如果你想调用者能够检索新的价值。


要完全诚实的,面向对象程序设计的主要原则是封装;理想情况下,LinkedListhead应该是内部维护的字段。为什么它应该是一个独立的部分?如果您真的希望将head隔离,那么为什么不是traverseadd是静态的?你应该尝试修改你的设计。我决定重写你的代码here

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); 
    } 
    } 
0
firstList.add(newNode,head); 

    /* 
    Part you should know is, head is a local variable pointing to null. 
    Passing head as parameter doesn't make it feasible to alter this local variable. 
    Your check is worthless. 
    Make public Node add(Node newNode, Node head) and return head from there. 
    */ 
    head=firstList.add(newNode,head); 

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

制作 “头” 参照另一节点具有对调用代码没有影响(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 
} 
+0

Java传递*值*,而不是引用;关键是在Java中,你实际上并不直接触及对象的价值(就像你可以用C++),而只是持有对它的引用。 – oldrinb

2

我觉得现在的问题是“添加”功能里面。你只是在函数范围内改变“head”的值,而不是在它之外。您可以找到有关Java对待传递参数值的方式的有用信息here

Java中LinkedList的一个很好的实现是here

0

这里更好地植入您的链接列表。请注意:

  1. _head应该是一个私有成员
  2. Node是一个内在机制。你应该给一个数据参数到您的add方法,而不是一个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(); 
    
    } 
    

    }

+0

请注意,您的链接列表是反向插入顺序。 – oldrinb

+0

为了这个案例是一个逻辑概念。这真的取决于你想要用你的代码做什么。我也可以编辑它以显示其他选项。 –

+0

当然,我只是说你的代码行为有所不同。 – oldrinb