Practical Examples
Real-World Generic Method Applications
1. Generic Swap Method
public class GenericSwapper {
public <T> void swap(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3, 4, 5};
String[] stringArray = {"A", "B", "C", "D"};
GenericSwapper swapper = new GenericSwapper();
swapper.swap(intArray, 0, 4);
swapper.swap(stringArray, 1, 2);
}
}
2. Generic Aggregation Methods
graph TD
A[Aggregation Methods] --> B[Sum]
A --> C[Average]
A --> D[Maximum]
A --> E[Minimum]
Numeric Aggregation Example
public class NumericAggregator {
public <T extends Number> double sum(List<T> numbers) {
return numbers.stream()
.mapToDouble(Number::doubleValue)
.sum();
}
public <T extends Comparable<T>> T findMax(List<T> items) {
return items.stream()
.max(Comparator.naturalOrder())
.orElse(null);
}
}
3. Generic Repository Pattern
Method |
Description |
Generic Signature |
Save |
Persist an entity |
<T> void save(T entity) |
FindById |
Retrieve by ID |
<T, ID> T findById(ID id) |
Delete |
Remove an entity |
<T> void delete(T entity) |
Implementation Example
public class GenericRepository<T, ID> {
private Map<ID, T> storage = new HashMap<>();
public void save(T entity, ID id) {
storage.put(id, entity);
}
public T findById(ID id) {
return storage.get(id);
}
public void delete(ID id) {
storage.remove(id);
}
}
4. Type-Safe Comparator
public class ComparatorUtility {
public <T extends Comparable<T>> Comparator<T> naturalOrder() {
return (a, b) -> a.compareTo(b);
}
public <T> Comparator<T> reverseOrder(Comparator<T> comparator) {
return comparator.reversed();
}
}
5. Flexible Conversion Methods
public class TypeConverter {
public <T, R> List<R> convertList(List<T> original, Function<T, R> converter) {
return original.stream()
.map(converter)
.collect(Collectors.toList());
}
}
graph TD
A[Generic Method Performance] --> B[Minimal Overhead]
A --> C[Type Erasure]
A --> D[JVM Optimization]
LabEx Learning Strategy
At LabEx, we recommend practicing these patterns through incremental complexity exercises to build robust generic programming skills.
Best Practices
- Keep generic methods focused
- Use bounded type parameters
- Leverage functional interfaces
- Minimize type casting
- Understand type erasure limitations
Common Pitfalls to Avoid
- Overusing complex generic signatures
- Ignoring performance implications
- Misunderstanding type bounds
- Excessive type parameters
Conclusion
Practical generic methods provide powerful abstractions that enhance code reusability, type safety, and overall software design flexibility.