Node Fields: data and next
Try This First
Given this declaration:
private static class Node<T> {
public T data;
public Node<T> next;
}
If you write Node<String> n = new Node<>();, what is the value of n.next immediately after construction?
Reveal
n.next is null. Java initializes reference fields to null by default, so the node does not point anywhere until you assign it explicitly.
What You Need To Walk In With
- A
Node<T>holds exactly two fields:dataof typeT(the payload) andnextof typeNode<T>(a reference to the following node). - The
nextfield is self-referential: its type is the same class that declares it. That one design choice is the entire linking mechanism of a linked list. - The last node in a chain always has
next == null. Thatnullis how traversal knows to stop. - Both fields are
publicinside a private inner class because the enclosingLinkedListclass reads and writes them directly (no getters needed when access is already restricted to the outer class). nextis notfinalbecause insert and remove operations must reassign it when the chain changes.
How It Works
A linked list is a chain of Node objects. Each node stores one value and a pointer (reference) to the node that comes after it:
private static class Node<T> {
public T data; // the value this node carries
public Node<T> next; // reference to the next node (null if none)
}
Because next has type Node<T>, a node can point to another node of the same kind. That is what “self-referential” means.
Picture a short chain of three nodes holding the strings “A”, “B”, and “C”:
head
|
[data="A" | next]-->[data="B" | next]-->[data="C" | next]-->null
Each box is a Node<String> object. The arrow from one box to the next is the next reference. The final arrow points to null to mark the end of the list.
The enclosing LinkedList<T> class keeps a single field Node<T> head that points to the first node. When head == null, the list is empty.
Building that three-node chain manually looks like:
Node<String> c = new Node<>();
c.data = "C";
c.next = null; // end of list
Node<String> b = new Node<>();
b.data = "B";
b.next = c; // b points to c
Node<String> a = new Node<>();
a.data = "A";
a.next = b; // a points to b
Node<String> head = a; // head of the list
Each pointer update is explicit: you set next to the object that should follow.
Worked Example: Predict, Then Check
Consider this chain (built exactly as above):
head -> [A] -> [B] -> [C] -> null
What does head.next.next.data evaluate to?
Reveal
head.next is the node holding “B”. head.next.next is the node holding “C”. So head.next.next.data is "C".
Following the chain step by step: head points to A, .next moves to B, .next again moves to C, then .data reads the payload.
A Common Mistake
A common error when writing Node for the first time is initializing next to a freshly constructed node instead of leaving it as null:
// Wrong
public Node<T> next = new Node<>();
This looks harmless but creates an infinite chain: every node you construct automatically holds another node, which holds another, and so on. Any traversal loop that checks current.next != null to stop will never stop, because next is never null. The fix is to leave next unassigned (Java sets it to null automatically) or to assign it explicitly only when you have a real node to link to. (Source: Liang 10e Ch 24)
Go Deeper (optional)
Once the full list is built, adding or removing a node in the middle is O(1) pointer work at the target position, but finding that position by following next references from head costs O(n). That tradeoff shapes every linked-list algorithm you will write this term. When you are ready, compare this structure to the dummy-head variant where a sentinel node always occupies position zero: the shape of the Node class is identical; only the list-level contract changes.
Check Yourself
Close the notes and answer each one from memory, then reveal it. Pulling an idea back from memory is one of the strongest ways to make it stick.
Check your understanding
Which statement correctly declares a generic Node inner class with data and next fields?
Why is Node called ‘self-referential’?
After this code runs, what is the value of b.next? Node<Integer> b = new Node<>(); b.data = 10; Node<Integer> c = new Node<>(); c.data = 20; b.next = c;
Why is the next field not declared final in a Node class?
Trace this chain: Node<String> x = new Node<>(); x.data = “X”; Node<String> y = new Node<>(); y.data = “Y”; x.next = y; // y.next is never assigned What does x.next.next evaluate to?