2013-03-18 9 views
0

我正在處理一個賦值的雙端隊列,並且我們遇到了一個問題,即對象引用在通過極端簡單的方法。當通過函數傳遞時節點失去對另一個對象的引用

一些重要的定義:

我們正在編寫
class Node { 
    String s; 
    Node prev; 
    Node next; 

    ... 

} 

class Sentinel extends Node { 
    Node prev; 
    Node next; 
    //Constructor uses that of Node 
} 

class Deque { 
    Sentinel start; 

    ... 
} 

一種方法去除一個deque一個節點,基於給定的字符串。

在雙端隊列:

public void removeSorted(String toRemove) { 
    // System.out.println(this.start); 
    // System.out.println(this.start.next); 
    this.start.next.removeSorted(toRemove); 
} 

註釋掉的println的顯示正確的哨兵和節點。

然後,在節點:

public void removeSorted(String toRemove) { 
    if (this.s.equals(toRemove)) { 
     // System.out.println(this.prev); 
     // System.out.println(this.prev.next); 
     this.prev.next = this.next; 
     this.next.prev = this.prev; 
    } else if (this.s.compareTo(toRemove) > 0) { 
     throw new RuntimeException("String does not exist in these nodes!"); 
    } else { 
     this.next.removeSorted(toRemove); 
    } 
} 

中的println爲this.prev輸出哨兵在第一遞歸,如所預期。但是,this.prev.next輸出null而不是節點。

此功能僅在嘗試刪除第一個節點時直接在Sentinel之後失敗。如果您嘗試刪除任何其他節點,它可以正常工作,並且試圖撥打this.prev.next將導致非空答案。

爲什麼參考在傳遞給函數時(緊隨其後)消失了,因爲我們在調用函數之前已經指出引用是直接存在的嗎?

+0

爲什麼你有這個'哨兵'呢?爲什麼不僅僅是'節點開始;'當列表爲空時用'start == null'? – hyde 2013-03-18 06:33:25

回答

0

您的問題代碼是錯誤的,或者您在NodeSentinel中都有相同的字段。這意味着,這兩個是不同的:

  • start.next是哨兵類,它隱藏場與從Node類同名next字段。
  • start.next.prev.next也是start的字段,但現在它是Node類的字段,因爲您可以通過節點引用來訪問它。

從Sentinel刪除prevnext。實際上刪除整個哨兵,它看起來像你用來「刪除」String s,這是不可能的,你不能「刪除」超級領域。或者,如果您需要/想要定位,請參閱下面的替代設計。

此外,這說明了爲什麼你應該使用干將制定者而不是直接訪問場...您的IDE可能有很好的重構工具來添加干將等(右鍵點擊場,請參閱「重構」子菜單) , 用它!如果你的IDE不具有,切換到其中一個做(我喜歡的NetBeans,但是Eclipse和IntelliJ都值得過),沒有這樣的IDE編寫Java是受虐狂演習...


而且,在Java中避免這種繼承。你或許應該有這種整體設計:

interface NodeInterface {...} 
public class Node implements NodeInterface {...} 
public class Sentinel implements NodeInterface {...} 

然後在NodeInterface,定義getter和setter方法,即應採取的參數以及返回NodeInterface類型。 Sentinel類當然不支持所有的接口方法,所以這些方法可以是return null; /什麼都不做,或者根據方法調用throw new IllegalStateException("Sentinel does not support Xxxx.");,如果調用該方法用於標記在調用代碼中存在缺陷(最好從拋出異常開始)。

如果這是學校的工作,你都沒有過的接口呢,然後更換interface NodeInterfaceclass NodeBase(最好是抽象的),但在「現實世界」這將是糟糕的代碼,因爲Java不支持多重繼承。

相關問題