All 15 Generics questions
More in Generics
Advertisement
Java › Generics

How would you write a generic interface (like a custom Repository<T, ID> pattern common in data-access layers) and implement it for a specific entity type?

Intermediate

Answer

A generic interface declares its type parameters at the interface level (interface Repository<T, ID>), with method signatures throughout the interface using those parameters, letting a concrete implementing class specify the actual types when it implements the interface (class UserRepository implements Repository<User, Long>), giving every method in that specific implementation properly typed parameters and return values without needing casts, while the interface itself remains fully reusable across entirely different entity types.
public interface Repository<T, ID> {
    T findById(ID id);
    List<T> findAll();
    T save(T entity);
    void deleteById(ID id);
}

public class UserRepository implements Repository<User, Long> {
    public User findById(Long id) { /* ... */ return null; }
    public List<User> findAll() { /* ... */ return List.of(); }
    public User save(User user) { /* ... */ return user; }
    public void deleteById(Long id) { /* ... */ }
}
Real-world example A data-access layer defines a single generic Repository<T, ID> interface, implemented separately for UserRepository (Repository<User, Long>), ProductRepository (Repository<Product, String>), and every other entity type, giving each implementation fully type-safe, properly-typed methods without any code duplication in the shared interface contract itself.

Common follow-ups: How does Spring Data JPA build heavily on exactly this generic repository interface pattern to auto-generate implementations?;What's the benefit of parameterizing the ID type separately from the entity type T, rather than assuming a fixed ID type?