Generics Basics

Generics allow you to write code that works with different types while keeping type safety.

Generics = reusable code + compile-time type checking


1. Why Use Generics?

Without generics:

List list = new ArrayList();

list.add("Hello");

String s = (String) list.get(0);

You need a cast.

With generics:

List<String> list = new ArrayList<>();

list.add("Hello");

String s = list.get(0);

No cast is needed, and Java checks the type at compile time.

list.add(10); // ERROR

Main benefits


2. Generic Class

A generic class uses a type parameter.

class Box<T> {

    private T value;

    void set(T value) {
        this.value = value;
    }

    T get() {
        return value;
    }
}

T is a placeholder for a type.

Use it like:

Box<Integer> box = new Box<>();

box.set(10);

Integer value = box.get();

You can use another type:

Box<String> box = new Box<>();

box.set("Hello");

String value = box.get();

So the same Box class works with different types.


3. Type Parameter vs Type Argument

class Box<T> { }

Here:

T → type parameter

When you use:

Box<Integer> box;

Here:

Integer → type argument

Easy way to remember:

Parameter = placeholder
Argument = actual type


4. Common Type Parameter Names

Java commonly uses:

Letter Meaning
T Type
E Element
K Key
V Value
N Number
S, U Additional types

Example:

Map<K, V>

means:

K = Key
V = Value

5. Diamond Operator <>

Instead of:

Box<Integer> box = new Box<Integer>();

you can write:

Box<Integer> box = new Box<>();

Java automatically infers Integer.

<> is called the diamond operator.


6. Multiple Type Parameters

A class can have multiple type parameters.

class Pair<K, V> {

    K key;
    V value;

    Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }
}

Use it:

Pair<String, Integer> pair =
    new Pair<>("Age", 22);

Here:

K → String
V → Integer

You can use completely different types:

Pair<String, String> pair =
    new Pair<>("Name", "Moxit");

7. Raw Types

A raw type means using a generic class without specifying its type.

Box box = new Box();

Instead of:

Box<String> box = new Box<>();

Raw types disable many generic type checks and can produce warnings.

Box rawBox = new Box();

rawBox.set(10);

Box<String> stringBox = rawBox; // Warning

Avoid raw types in new code.

They mainly exist for compatibility with old Java code.


8. Unchecked Warnings

When raw types are mixed with generics, Java may produce an unchecked warning.

Example:

Box rawBox = new Box();

Box<Integer> box = rawBox;

Compile with:

javac -Xlint:unchecked Example.java

to see more detailed warnings.


9. Generic Methods

A method can have its own type parameter.

static <T> void print(T value) {
    System.out.println(value);
}

Now it works with different types:

print(10);
print("Hello");
print(3.14);

The important syntax is:

<T> void

The <T> comes before the return type.


10. Generic Method with Multiple Types

static <K, V> void printPair(K key, V value) {
    System.out.println(key + " = " + value);
}

Use:

printPair("Age", 22);
printPair(1, "Apple");

Java usually figures out the types automatically.


11. Bounded Type Parameters

Sometimes you don't want to allow every type.

For example, you want only numbers.

Use:

<T extends Number>

Example:

static <T extends Number> void printNumber(T number) {
    System.out.println(number);
}

These work:

printNumber(10);       // Integer
printNumber(3.14);     // Double
printNumber(10L);      // Long

But:

printNumber("Hello");  // ERROR

because String does not extend Number.

extends in generics means "this type must be this type or a subtype of it."


12. Multiple Bounds

You can have multiple bounds:

<T extends A & B & C>

Example:

class MyClass<T extends Animal & Runnable> {
}

The rule is:

If there is a class, it must come first, followed by interfaces.

<T extends Animal & Runnable & Serializable>

Quick Revision

Concept Meaning
Generic Code that works with different types safely
T Type parameter
Integer in Box<Integer> Type argument
<> Diamond operator
Box<T> Generic class
<T> method() Generic method
Raw type Generic type without type argument
T extends Number Restricts T to Number or subclasses
T extends A & B Multiple bounds
Main benefit Type safety + reusable code

The easiest way to understand Generics

Without generics:

Box box = new Box();
box.set("Hello");

String s = (String) box.get();

With generics:

Box<String> box = new Box<>();
box.set("Hello");

String s = box.get();

Generics tell Java what type your code is supposed to work with, so Java can check it for you at compile time.