Как клонировать кругово связанный список - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь клонировать список с круговой связью так же, как вы клонируете список с уникальной связью, но у меня возникли проблемы.

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

public static void main(String[] args) throws CloneNotSupportedException 
  {

  CircularlyLinkedList<String> circularList = new 
  CircularlyLinkedList<String>();
  circularList.addFirst("1");
  circularList.addLast("2");
  circularList.addLast("3");
  circularList.addLast("4");


  CircularlyLinkedList<String> newList = new CircularlyLinkedList<String>();
  newList= circularList.clone();
  System.out.println(newList);
  }
@SuppressWarnings("unchecked")
public CircularlyLinkedList<E> clone() throws CloneNotSupportedException 
{
  // always use inherited Object.clone() to create the initial copy
    CircularlyLinkedList<E> other = (CircularlyLinkedList<E>) super.clone(); // safe cast
    if (size > 0) {                    // we need independent chain of nodes
        other.head = new Node<>(head.getElement(), null);
        Node<E> walk = head.getNext();      // walk through remainder of original list
        Node<E> otherTail = other.head;     // remember most recently created node
        while (walk != null) {              // make a new node storing same element
          Node<E> newest = new Node<>(walk.getElement(), null);
          otherTail.setNext(newest);     // link previous node to this one
          otherTail = newest;
          walk = walk.getNext();
        }
      }
    return other;

}

Этот код работает при использовании односвязных списков. Ожидаемый вывод - это связанный список, напечатанный дважды, но фактическим выводом является исключение «CloneNotSupported». Обратите внимание, что программа не выдает это исключение, когда clone () возвращает нулевой список.

1 Ответ

0 голосов
/ 24 января 2019

Вот проблема, я думаю:

CircularlyLinkedList<E> other = (CircularlyLinkedList<E>) super.clone(); 

Теперь вы не сказали нам, что такое суперкласс CircularlyLinkedList, но есть доказательства:

  1. Он не реализует интерфейс маркера Cloneable.
  2. Он не переопределяет метод clone, который он наследует от Object.

С этой комбинацией super.clone() бросит CloneNotSupportedException.Это объясняется в javadoc .


Реальная проблема заключается в том, почему ypou вызывает super.clone()?

Если вы делаете это, потому что суперкласс имеетсостояние, которое необходимо скопировать в клоне, который вы создаете, тогда он (суперкласс) должен обеспечить некоторый способ клонирования;т. е. для этого нужно выполнить одно из вышеперечисленных ... или предоставить «конструктор копирования» или аналогичный.

Если вы делаете это только для того, чтобы заставить печатать работать , то вам, вероятно, следуетсделайте что-то вроде этого:

    CircularlyLinkedList<E> other = new CircularlyLinkedList<>(); 

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


Я отмечаю этот комментарий:

// always use inherited Object.clone() to create the initial copy

Если он предназначен для значения всегда для этого класса , то просто исправьте его так, чтобы он соответствовал тому, что вы на самом деле делаете.Помните, что вы можете это сделать только в том случае, если суперкласс является клонируемым ... которого в настоящее время нет!

Если он предназначен для записи того, что это «лучшая практика» (или что-то подобное; см. this) делать это во всех случаях, это просто неправильно:

  • Как я объяснил, вы не можете сделать это во всех случаях.
  • Хотя есть аргументы, что может быть нежелательно использовать другой метод для дублирования состояния суперкласса, подкласс имеет право делать предположения о своем суперклассе в ОО-дизайне.
  • И, кроме того, позвонив super.clone(), вы делаете предположение ... что clone() будет работать!
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...