Generics Summary
Generic Types Concept
- Allow type parameters in class/interface definitions
- Enable type-safe collections/operations
- Prevent runtime type errors
- Example:
class Box<T> { private T item; public void put(T item) { this.item = item; } public T get() { return item; } }
Type Parameters
- Commonly used letters:
- T for type
- E for element
- K for key
- V for value
- S,U,V for multiple types
- Example:
class Pair<K,V> { private K key; private V value; }
Parameterized Type
- A concrete type created by specifying actual types for generic parameters
- Replaces generic type parameters with real types
- Creates type-safe class instances
- Example:
// This is a generic type (not parameterized yet): class Array<T> { // T is just a placeholder private T[] elements; } // These are parameterized types: Array<String> words = new Array<>(); // T becomes String class StringArray extends Array<String> { } // Array<T> is instantiated as Array<String> // Invalid parameterized type examples: // class Array<String> { } // ERROR: Cannot use concrete type in class definition // Array<int> numbers; // ERROR: Cannot use primitive types // Array<T> generic; // ERROR: T is not defined in this context
Bounded Type Parameters
- Restrict type parameters to certain types
- Use extends keyword
- Can bound to class or interface
- Example:
class NumberBox<T extends Number> { private T number; public double getValue() { return number.doubleValue(); // OK because T extends Number } }
Generic Methods
- Methods with their own type parameters
- Type parameter before return type
- Example:
public static <T> void printArray(T[] array) { for (T element : array) { System.out.println(element); } }
Type Inference
- Java can infer type arguments
- Diamond operator <> for constructors
- Example:
List<String> list = new ArrayList<>(); // type inferred Box<Integer> box = new Box<>(); // type inferred
Generic Type Restrictions
- Cannot create arrays of generic types
- Cannot create generic exceptions
- Cannot use primitives directly
- Example:
// Not allowed: T[] array = new T[10]; // compile error // Use this instead: T[] array = (T[]) new Object[10];
Best Practices
- Use generics for type safety
- Prefer bounded wildcards for flexibility
- Document type parameter meanings
- Keep type parameter names meaningful
- Use generic collections over raw types
- Consider type erasure implications