Concepts / Simple Generic Classes

Simple Generic Classes

A type parameter is a placeholder written in angle brackets after a class name, and it works much like a formal parameter in a subroutine.

  • Programming
Interactive lab

Try it: Stack and Queue

The difference between a stack (last in, first out) and a queue (first in, first out).

How it works

  1. A stack adds (push) and removes (pop) at the same end, the top — the last item added leaves first.
  2. A queue adds (enqueue) at the back and removes (dequeue) from the front — the first item added leaves first.
  3. peek / front look at the next item without removing it.
  4. Adding to a full structure is an overflow; removing from an empty one is an underflow.

Default run (3 steps): Stack (bottom → top): 4, 7. 2 of 8 slots used. Choose an operation. Example: push 9. … Stack is now: 4, 7, 9. Size 3/8.

Simplified: Fixed capacity of 8 items so overflow can be shown; Python lists and collections.deque grow as needed.

Educational simulation

Loading the simulation…

One Queue for Many Element Types

Suppose you want a single queue implementation that can hold strings, integers, or colors, without writing a separate queue class for each element type. A generic class solves this problem by leaving one spot in its definition open. That open spot is called a type parameter, and the class is written so that the same code works no matter which real type fills it.

What do you think happens?

If the placeholder name in a generic class is changed from ItemType to T, does the class behave differently?

  • Yes, the queue stores different values

  • No, the name is only a label and the meaning stays the same

Reveal answer
Answer:

No, the class behaves exactly the same. The name of a type parameter is arbitrary.

The type parameter is only a label used inside the class. Renaming ItemType to T changes how the code reads, not what the class does or how it is used. You will return to this idea when choosing names later in the article.

Before reading on, think about the Queue class as a template. Which parts of it would need a real type name, and which parts would be identical for every element type? Keep your answer in mind, because the next section traces exactly what the placeholder does inside the class.

Reading a Generic Class Header

The header of a generic class is where the placeholder is introduced. The general form is a class name followed by the type parameter in angle brackets. Read the header from left to right. The angle-bracket part is the only place where the placeholder is declared. Everything inside the braces refers back to that name.

classdeclares a classQueueclass name<ItemType>type parameter declaredhereItemTypeused as return type ofdequeueItemTypeused as type of enqueueparameterrefers back torefers back to
Which token declares the placeholder, and which tokens only use it? The angle-bracket part declares the type parameter; the body refers back to it.

When you read a method inside the body, treat ItemType the same way you would treat String or int. It is a type name, but one that has not yet been given a specific value. The header tells you where it is introduced; the body tells you where it is used.

Four Jobs of the Placeholder

Inside the Queue class, the placeholder does four different jobs. It is the return type of dequeue. It is the type of the formal parameter item in enqueue. It is the actual type parameter given to the LinkedList that stores the items, so the internal list is declared as a LinkedList of the placeholder type. The fourth job is less obvious: the class is written only in terms of the placeholder, so it never commits to any particular element type.

java
Notes on the code
  • The header declares ItemType once, in angle brackets after the class name.
  • The field items is a LinkedList whose element type is the placeholder.
  • The parameter item of enqueue has the placeholder as its type.
  • The return type of dequeue is the placeholder.

How a Type Parameter Is Bound

A type parameter behaves like a formal parameter in a subroutine. A subroutine's formal parameter is a stand-in that receives a real value at each call. A type parameter is a stand-in that receives a real type name at each use of the class. In both cases, the same definition is written once and then supplied with concrete material when it is actually used.

The placeholder is replaced by an actual type name when the class is used to declare a variable or create an object. Because of this, one class definition gives you a whole family of parameterized types. The source describes Queue<String>, Queue<Integer>, and Queue<Color> as all valid uses of the same class.

Queueone generic classQueue<String>ItemType bound to StringQueue<Integer>ItemType bound to Integerparameterized as Stringparameterized as Integer
How do Queue<String> and Queue<Integer> relate to the single Queue class, and why can they not be mixed?

Tracing Queue<String> Through the Class

Now follow one concrete declaration. The code below fills the placeholder with String. Wherever the class body said ItemType, the code is now dealing with String. Nothing in the Queue class was rewritten to make this happen; the same definition is simply used with a different type name.

java
Output
next holds the value "Ada"
Notes on the code
  • Queue<String> replaces ItemType with String in every place the class uses it.
  • enqueue now accepts a String parameter.
  • dequeue now returns String, so the result can be assigned to a String variable without any cast.
Before
class Queue<ItemType>
  dequeue() returns ItemType
  enqueue(ItemType item)
  LinkedList<ItemType>

ItemType is an open placeholder in the class definition.

After
Queue<String>
  dequeue() returns String
  enqueue(String item)
  LinkedList<String>

The same placeholder is now bound to String everywhere it appeared.

ItemTypereturn type of dequeueStringreturn type of dequeueItemTypeparameter of enqueueStringparameter of enqueueLinkedList<ItemType>internal storageLinkedList<String>internal storage
When Queue<String> is written, what happens to every occurrence of the type parameter inside the class?

Mistakes Beginners Make with Type Parameters

  • Common mistake

    Believing that renaming the type parameter changes what the class does

    What it looks like

    Changing class Queue<ItemType> to class Queue<Element> and updating every use to match.

    Why it fails

    The name of a type parameter is arbitrary. The source states that renaming ItemType to T has no effect on the meaning of the class or how it is used.

    Do this instead

    Treat the name as a readability choice. Pick a name that is clear to the reader of the code.

  • Common mistake

    Assuming a generic class is rewritten for each element type

    What it looks like

    Expecting a separate StringQueue source file to exist after writing Queue<String>.

    Why it fails

    The class definition stays the same. The placeholder is only replaced by an actual type name at the point of use.

    Do this instead

    Look for one class definition and many parameterized uses of it.

  • Common mistake

    Mixing parameterized types that were bound to different types

    What it looks like

    Passing an Integer value to enqueue on a variable declared as Queue<String>.

    Why it fails

    Queue<String> and Queue<Integer> are distinct types after binding. A String-bound queue expects String items, so an Integer does not fit its enqueue parameter.

    Do this instead

    Make the value's type match the type that was bound when the variable was declared.

Spotting a Mismatch in a Trace

Trace the following statements step by step. For each step, state what type the placeholder has been replaced with, and say which line would first show a mismatch if one exists.

EASY

Given Queue<String> names = new Queue<String>(); followed by names.enqueue("Ada"); and then names.enqueue(42);, identify the type bound to ItemType, the type of the item parameter in the second enqueue call, and the statement where the mismatch appears.

Hints
  • Find the angle-bracket type on the declaration line; that is the type ItemType was replaced with.
  • Compare the argument 42 with the parameter type that the placeholder became.
  • The first enqueue call matches the bound type; the second one does not.

A mismatch shows up at the call site where a value of the wrong type enters the class, not inside the class body. The class body is written against the placeholder and does not change. Checking the declaration and then the first method call that uses the wrong value will locate the problem.

Key Takeaways

  • A type parameter is a placeholder written in angle brackets after a class name, and it works much like a formal parameter in a subroutine.
  • Inside a generic class, the placeholder can serve as a return type, a parameter type, and the actual type parameter of another generic class such as LinkedList.
  • Writing a parameterized type such as Queue<String> replaces the placeholder with an actual type name everywhere it appears, and one class definition yields a family of such types.
  • The name of a type parameter is arbitrary and does not change what the class does, so choose a name that is clear to readers.
  • A type mismatch shows up where a value of the wrong type enters the class, so trace the declaration and then the method calls that use it.