πŸ“ What You’ll Learn

  • What generics are and why they’re useful
  • How to use generic classes, methods, and interfaces
  • Bounded types and wildcards
  • Real-world examples with collections

🧠 What Are Generics?

Generics allow you to parameterize types. Instead of writing different classes for different data types, you can write one generic class or method.

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

βœ… Helps catch errors at compile time
βœ… Avoids explicit casting
βœ… Improves code reusability

πŸ“¦ Generic Class Example

class Box<T> {
    private T value;

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

Use it like this:

Box<String> b1 = new Box<>();
b1.set("Hello");
System.out.println(b1.get());

Box<Integer> b2 = new Box<>();
b2.set(42);

πŸ› οΈ Generic Methods

public class Utils {
    public static <T> void printArray(T[] array) {
        for (T item : array) {
            System.out.println(item);
        }
    }
}

🧱 Bounded Type Parameters

Use bounds to restrict the types:

class MathBox<T extends Number> {
    public double square(T num) {
        return num.doubleValue() * num.doubleValue();
    }
}

πŸŒ€ Wildcards – ?

Used when you want flexibility, especially with inheritance:

List<?> list = new ArrayList<String>(); // accepts any type

Wildcard types:

Syntax Meaning
<?> Any type
<? extends T> Any subtype of T
<? super T> Any supertype of T

πŸ”„ Generics in Collections

Collections use generics extensively:

List<String> list = new ArrayList<>();
list.add("Hello");
// list.add(123);  // ❌ Compile error!

πŸ’‘ Why Use Generics?

βœ… Compile-time type safety
βœ… No need for casting
βœ… Reusability
βœ… Cleaner APIs (especially for libraries and frameworks)

πŸ“˜ Recap

  • Generics make your code safer and cleaner
  • Use <T> to define generic types
  • Wildcards offer flexibility (<?>, <? extends>, <? super>)
  • Collections and many Java APIs use generics under the hood