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
-
Type safety
-
Fewer casts
-
Reusable code
-
Errors caught at compile time
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.
extendsin 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.