Java Generics

Type-safe collections and parameterized types for compile-time type checking

java (5+) 2025-11-03 generics type-safety collections

Description

Generics in Java enable you to write type-safe code that works with different types. They provide compile-time type checking and eliminate the need for explicit type casting.

Key Concepts

  • Type parameters: Placeholders like <T>, <E>, <K, V>
  • Bounded types: Restrict type parameters with extends or super
  • Wildcards: ?, ? extends Type, ? super Type
  • Type erasure: Generics are erased at runtime, only exist at compile time
  • Raw types: Non-parameterized generic types (not recommended)

Common Use Cases

  • Type-safe collections
  • Generic methods and classes
  • Parameterized interfaces
  • Bounded type parameters for constraints

Code

RAW
import java.util.*;// Generic classpublic class Box<T> {    private T value;        public void setValue(T value) {        this.value = value;    }        public T getValue() {        return value;    }        // Generic method    public <U> void printValue(U value) {        System.out.println("Value: " + value);    }}// Bounded type parameterclass NumberBox<T extends Number> {    private T number;        public double getDoubleValue() {        return number.doubleValue();    }}// Multiple type parametersclass Pair<K, V> {    private K key;    private V value;        public Pair(K key, V value) {        this.key = key;        this.value = value;    }        public K getKey() { return key; }    public V getValue() { return value; }}// Generic method with wildcardclass Utils {    public static void printList(List<?> list) {        for (Object item : list) {            System.out.println(item);        }    }        // Upper bounded wildcard    public static double sum(List<? extends Number> numbers) {        double sum = 0.0;        for (Number n : numbers) {            sum += n.doubleValue();        }        return sum;    }        // Lower bounded wildcard    public static void addNumbers(List<? super Integer> list) {        list.add(1);        list.add(2);    }}
RAW
// Generic Box usageBox<String> stringBox = new Box<>();stringBox.setValue("Hello");String value = stringBox.getValue(); // No casting neededBox<Integer> intBox = new Box<>();intBox.setValue(42);// Bounded type usageNumberBox<Integer> intNumberBox = new NumberBox<>();NumberBox<Double> doubleNumberBox = new NumberBox<>();// NumberBox<String> stringBox = new NumberBox<>(); // Compile error!// Pair usagePair<String, Integer> pair = new Pair<>("age", 25);String key = pair.getKey();Integer val = pair.getValue();// Generic collectionsList<String> names = new ArrayList<>();names.add("Alice");names.add("Bob");String first = names.get(0); // Type-safeMap<String, Integer> ages = new HashMap<>();ages.put("Alice", 30);ages.put("Bob", 25);Integer aliceAge = ages.get("Alice"); // Type-safe// Wildcard usageList<Integer> ints = Arrays.asList(1, 2, 3);Utils.printList(ints);List<String> strings = Arrays.asList("a", "b");Utils.printList(strings);// Upper boundedList<Integer> integers = Arrays.asList(1, 2, 3);double sum1 = Utils.sum(integers);List<Double> doubles = Arrays.asList(1.5, 2.5);double sum2 = Utils.sum(doubles);

Comments

No comments yet. Be the first to comment!