2015-07-27 2 views
4

Я работаю через Алгоритмы Четвертое издание (Sedgewick) и запутано некоторыми упражнениями связанного списка, которые, похоже, требуют реализовать статические методы для нестатических узлов. Например,Статические методы для операций над внутренним классом

1.3.27 Написать метод, который принимает max() ссылку на первый узел в связанного списка в качестве аргумента и возвращает значение максимального ключа в списке. Предположим, что все ключи являются положительными целыми числами и возвращают 0, если список пуст.

или

1.3.31 Реализация вложенного класса DoubleNode для построения двусвязных списков, , где каждый узел содержит ссылку на элемент, предшествующий его и пункт после него в список (null если такого товара нет). Затем реализовать статические методы для следующих задач: вставить в начало , вставить в конец, удалить с начала, удалить из конец, вставить перед данным узлом, вставить после заданного узла и удалить данный узел ,

Как я понимаю (и подтверждено SO ответы here и here) это не представляется возможным. Как и ожидалось, Eclipse дает ошибки, если я пытаюсь написать статический метод суперкласса:

public class DoublyLinkedList<Item> { 

    public static void insertStart(DoubleNode first) { 
     // implementation 
    } 

    private class DoubleNode { 
     Item item; 
     DoubleNode next; 
     DoubleNode previous; 

    } 
} 

(дает ошибку Cannot make a static reference to the non-static type DoubleNode); или во внутреннем классе:

public class DoublyLinkedList<Item> { 

    private class DoubleNode { 
     Item item; 
     DoubleNode next; 
     DoubleNode previous; 

     public static void insertStart(DoubleNode first) { 
      // implementation 
     } 
    } 
} 

(выдает ошибку The method insertStart cannot be declared static; static methods can only be declared in a static or top level type).

Я мог бы написать необходимые методы как методы экземпляра для класса DoublyLinkedList, и это казалось бы самым естественным для меня.

Однако, я чувствую, что, возможно, я пропустил что-то важное здесь. Автор явно заявляет, что методы должны быть статическими, а также предлагает взять ссылку на первый узел в качестве аргумента (что было бы лишним для метода экземпляра, поскольку класс будет иметь переменную экземпляра для первого узла). Что мне не хватает?

ответ

4

Вы можете сделать вложенные классы как static. Вы потеряете ограничение наличия экземпляра класса вшита родительским, но это позволит вам работать на DoubleNode с из статического метода:

// This will compile 
public class DoublyLinkedList<Item> { 

    public static <T> void insertStart(DoublyLinkedList<T> list, DoubleNode<T> first) { 
     // implementation 
    } 

    private static class DoubleNode<E> { 
     E item; 
     DoubleNode<E> next; 
     DoubleNode<E> previous; 

    } 
} 

Две вещей, чтобы заметить здесь: Как вы можете видеть, когда делаете внутренние class static, вам необходимо указать его собственный параметр типа (в данном случае E). В вашем коде вам не нужно было этого делать, потому что у любого экземпляра DoubleNode было гарантировано наличие экземпляра DoublyLinkedList, который уже определяет, что будет Item.

Во-вторых, вам необходимо ввести параметр типа для вашего статического метода («<T>»), чтобы вы могли применять один и тот же общий тип для обоих аргументов. Вы также могли бы сделать это и уйти с ним:

public static void insertStart(DoublyLinkedList<?> list, DoubleNode<?> first) { 
    ... 
} 

В случае, если вам интересно, это также, как это делается в LinkedList реализации JDK в:

// Source : Oracle JDK 1.7.0_67 lib - inside LinkedList class 
private static class Node<E> { 
    E item; 
    Node<E> next; 
    Node<E> prev; 

    Node(Node<E> prev, E element, Node<E> next) { 
     this.item = element; 
     this.next = next; 
     this.prev = prev; 
    } 
} 

Как Замечание, Я согласен с тем, что более естественно писать эти методы в качестве членов экземпляра; вот как это делается в библиотеках ООП. У меня нет копии книги Седжуика, но похоже, что он одновременно пытается научить вас одновременно вложенным манипуляциям классов и спискам;)

+0

Спасибо. Интересно видеть реализацию JDK. В чем важность этого ограничения в этом контексте? – TheZero

+1

Ограничение - это то, что мешает успешному компиляции кода. Он должен убедиться, что вы не можете использовать переменную для хранения «независимого» объекта «DoubleNode» или определить статический или внешний метод, который возвращает значение типа «DoubleNode». Дело в том, чтобы поощрять инкапсуляцию («хранить все вещи« DoubleNode »внутри методов экземпляра DoublyLinkedList»), но в этом случае это противоречит утверждению «сделать статический метод». –

+0

Здесь вы можете прочитать базовое введение в различные типы вложенных классов: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html –

Смежные вопросы