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;

    ...
}

私たちが書いているメソッドの 1 つは、指定された文字列に基づいて両端キューから Node を削除します。

両端キューで:

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

コメントアウトされた println は、正しい Sentinel と Node を示しています。

次に、ノードで:

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

this.prev期待どおり、最初の再帰で Sentinel を出力するための println 。ただし、this.prev.next はノードの代わりに null を出力します。

この関数は、Sentinel の直後の最初のノードを削除しようとしたときにのみ失敗します。他のノードを削除しようとすると、正常に機能し、呼び出しを試みるとthis.prev.nextnull 以外の応答が返されます。

関数を呼び出す直前に参照が存在することを示したのに、関数に渡すとき (直後) に参照が消えるのはなぜですか?

4

1 に答える 1

0

質問コードが間違っているか、 と の両方に同じフィールドがありNodeますSentinel。これは、次の 2 つが異なることを意味します。

  • start.nextnextSentinel クラスのフィールドであり、Node クラスから同じ名前のフィールドを非表示にします。
  • start.next.prev.nextも のフィールドですがstart、Node 参照でアクセスするため、Node クラスのフィールドになりました。

Sentinel からprevとを削除します。next実際には Sentinel 全体を削除してくださいString s。これは不可能であり、スーパー クラス フィールドを「削除」することはできません。または、センチネルが必要/必要な場合は、以下の代替設計を参照してください。

また、これは、フィールドに直接アクセスする代わりに、ゲッターセッターを使用する必要がある理由を示しています... IDE には、おそらくゲッターなどを追加するための優れたリファクタリング ツールがあります (フィールドを右クリックし、「リファクタリング」サブメニューを参照)、それを使用してください! IDE にそれがない場合は、それがあるものに切り替えてください (私は NetBeans を好みますが、Eclipse と IntelliJ も価値があります)。そのような IDE なしで Java を書くことはマゾヒズムの練習です...


また、Java では、そのような継承は避けてください。おそらく、次のような全体的な設計が必要です。

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

次に、 でNodeInterfacegetter と setter を定義します。これらは、パラメーターと戻り値NodeInterfaceの型を受け取る必要があります。Sentinelもちろん、クラスはすべてのインターフェイスメソッドをサポートしているわけではないため、これらのメソッドはreturn null;/何もしないかthrow new IllegalStateException("Sentinel does not support Xxxx.");、メソッドに応じて、センチネルのそのメソッドの呼び出しがコードの呼び出しのバグであるかどうかに依存します(例外をスローすることから始める方がよいでしょう)。

これが学校の課題であり、まだインターフェイスを調べていない場合は、(抽象的であることが望ましい) に置き換えますがinterface NodeInterfaceclass NodeBaseJava は多重継承をサポートしていないため、「現実の世界」ではこれは悪いコードになります。

于 2013-03-18T05:46:50.693 に答える