Generics
Generic Interfaces
Analyze generic interface declarations, implementation patterns, and standard utility API contracts.
Interview: Focuses on generic interfaces (Comparable, Comparator), subclass implementation choices, and raw implementations.
A Generic Interface is an interface that parameterizes its method signatures. Like generic classes, it allows client classes to specify concrete type arguments when implementing or extending the interface.
Typed Contracts
Defines methods using type parameters: interface Service<T> { void process(T data); }.
Generic Subclasses
Classes can implement the interface generically, propagating type parameters: class Impl<T> implements Service<T>.
Concrete Subclasses
Classes can bind type parameters to concrete classes: class StringImpl implements Service<String>.
Implementing Generic Interfaces
When a class implements a generic interface, it has two choices:
- Bind Concretely: The class resolves the type parameter to a concrete class (e.g.
implements Comparable<User>). The overriding methods are generated with concrete signatures. - Propagate Generically: The class remains generic, propagating its type parameters to the interface:
class Repository<T> implements Dao<T>.
Common Pitfalls
- Using raw interface types: Implementing raw interface signatures (e.g.
class Impl implements Dao), which raises compiler warnings and removes type safety. - Mismatched signatures: Mixing concrete and generic implementations, leading to compile-time type errors.
Best Practices
- Define clear contracts: Use generic interfaces to define standard components (e.g. repositories, processors, validators).
- Align with Comparable/Comparator: Follow standard library conventions when designing custom comparison or sorting interfaces.
Interview-Relevant Information
Q1: What are the two ways a class can implement a generic interface?
Answer: 1) Concrete implementation: the subclass binds the type parameter to a concrete type (e.g. class StringImpl implements Service<String>). 2) Generic implementation: the subclass remains generic and propagates the type parameter (e.g. class MyImpl<T> implements Service<T>).
Q2: Why should you avoid implementing raw interface types?
Answer: Implementing a raw interface type removes compile-time type checks. Methods default to using Object, which forces manual type casting and increases the risk of runtime type errors.
Quick Checklist
Can you define a generic interface, write class headers for both concrete and generic implementation patterns, and explain how method signatures change under each? If yes, you understand generic interfaces.
Use Cases
Building generic database access layers (DAOs/Repositories) in enterprise software.
Defining pluggable processing pipelines using strategy patterns.
Common Mistakes
Implementing raw interfaces in new class structures, disabling compiler type checks.
Failing to override methods using matching parameter types.