Не понимаю, как работает добавление элемента в конец связного списка java

Допустим, вот код связного списка, простые три операции: добавление в начало списка, в конец, и вывод списка. Единственный момент, который я не понимаю, это как работает добавление в конец списка. В "начало" всё просто, мы создаем новый узел, присваиваем ему значение старый ссылки, в свою очередь "началу" или "голове" присваиваем значение нового узла. А вот, как работает эти строки: tail.next = newNode; tail = newNode; для меня загадка. Ведь здесь не создаются новые экземпляры (tail это единственный экземпляр класса MyLinkedList), при этом при добавление нового элемента, ссылки на предыдущие элементы почему то не теряются. Прошу объяснить доступным для такого не далекого человека языком, именно этот момент.

public class MyLinkedList {
    Node head;
    Node tail;

 

    void addToHead(int data) {
        Node newNode = new Node(data);

        if (head == null) {
            head = newNode;
            tail = newNode;
        } else {
           newNode.next = head;
           head = newNode;
        }

    }

    void addToTail(int data) {
        Node newNode = new Node(data);

        if (tail == null) {
            head = newNode;
            tail = newNode;
        } else {
            tail.next = newNode;
            tail = newNode;
        }
    }

    void printAll() {
        Node node = head;
        while (node != null) {
            System.out.print(node.data + " ");
            node = node.next;
        }
    }

    static class Node {
        Node next;
        int data;
        

        Node(int data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return Node.class.getName() + " data: " + data;
        }
    }
}


Ответы (1 шт):

Автор решения: MBo

Было

 a  ->  b  ->  с ->  NULL
 ^             ^ 
 |             |   
head           tail 

tail является синонимом узла c

Добавляем в конец. tail пока равен c, поэтому tail.next = newNode; то же самое, что с.next = newNode;

 a  ->  b  ->  с ->  d  -> null
 ^             ^ 
 |             |   
head           tail 

Делаем tail синонимом узла d (tail = newNode;)

 a  ->  b  ->  с ->  d  -> null
 ^                   ^ 
 |                   |   
head                tail 
→ Ссылка