JVM / Java / OOP / Generics

1. Generics in Java

A generic type is a class or method that can operate on different data types while still providing type safety. Without generics, everything is threated as Object. With generics MyClass< T >, Java enforces the type at compile time. When you write Box< String > T becomes String (T is a type placeholder).
 
public class TypePlaceholder {
    public static void main(String[] args) {
        
        // Non-generic class (unsafe)
        // ==========================
        MyUnsafeClass A = new MyUnsafeClass();
        A.set(10);
        System.out.println(A.get());        // 10

        A.set("John");                      // allowed (but unsafe)
        System.out.println(A.get());        // John

        // Generic class (safe)
        // ====================
        MyClass<Integer> B = new MyClass<>();
        B.set(10);
        System.out.println(B.get());        // 10

        /* 
            This compile but will crash at runtime:
            Integer x = (Integer) A.get();

            This is safe, will give compile-time error:
            B.set("John"); // ❌ compile-time error
            
            This is the whole point of generics.
        */
    }
}

class MyUnsafeClass {
    private Object obj;
    public void set(Object o) { 
        obj = o;
    }
    public Object get() { 
        return obj; 
    }
}

class MyClass<T> {
    private T t;
    public void set(T t) { 
        this.t = t; 
    }
    public T get() { 
        return t; 
    }
}

2. Multiple Types

A generic class can have more than one type parameter (Box, Map, Entry). Each type parameter must have a unique name.
 
package oop.generics;

public class MultipleTypes {
    public static void main(String[] args) {
        
        // Box<T, U> can accept two different types
        Box<Integer, Integer> box = new Box<>();
        box.set(10);
        
        System.out.println(box.get()); // 10
    }

    // Generic class with one type parameters: T
    static class Box<T, U> {

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

    // static class Word<T, T> {} // ❌ Error: Duplicate type parameter T
}

3. Generics Limitations

Generic type cannot be used in static context. Static fields belong to the class, not to individual objects. Generics cannot use primitives. After compilation, generics become Objects. Primitives (int, double, etc.) are not objects. Use their wrapper classes insteed.
 
static T value;   // ❌ compiler error

Box<int> box;    // ❌ not allowed

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




References: