From Effective Java 2/e by Joshua Bloch
Static utility methods are particularly good candidates for generification
All of the “algorithm” methods in Collections (such as binarySearch and sort) have been generified
The type parameter list, which declares the type parameter, goes between the method’s modifiers and its return type
// Uses raw types - unacceptable! (Item 23) public static Set union(Set s1, Set s2) { Set result = new HashSet(s1); result.addAll(s2); return result; } // Generic method public static <E> Set<E> union(Set<E> s1, Set<E> s2) { Set<E> result = new HashSet<E>(s1); result.addAll(s2); return result; }
- Compiles without generating any warnings
- Provides type safety as well as ease of use
Type inference
- The compiler figures out the value of the type parameters by examining the types of the method arguments
// Type inference for generic contstructor Map<String, List<String>> anagrams = new HashMap<>(); // Generic static factory method public static <K, V> HashMap<K, V> newHashMap() { return new HashMap<K, V>(); } // Parameterized type instance creation with static factory Map<String, List<String>> anagrams = newHashMap();
Generic singleton pattern
// Generic singleton factory pattern private static UnaryFunction<Object> IDENTITY_FUNCTION = new UnaryFunction<Object>() { public Object apply(Object arg) { return arg; } }; // IDENTITY_FUNCTION is stateless and its type parameter is // unbounded so it's safe to share one instance across all types. @SuppressWarnings("unchecked") public static <T> UnaryFunction<T> identityFunction() { return (UnaryFunction<T>) IDENTITY_FUNCTION; } // Sample program to exercise generic singleton public static void main(String[] args) { String[] strings = { "jute", "hemp", "nylon" }; UnaryFunction<String> sameString = identityFunction(); for (String s : strings) System.out.println(sameString.apply(s)); Number[] numbers = { 1, 2.0, 3L }; UnaryFunction<Number> sameNumber = identityFunction(); for (Number n : numbers) System.out.println(sameNumber.apply(n)); }
Recursive type bound
for a type parameter to be bounded by some expression involving that type parameter itself
public interface Comparable<T> { int compareTo(T o); } // Returns the maximum value in a list - uses recursive type bound public static <T extends Comparable<T>> T max(List<T> list) { Iterator<T> i = list.iterator(); T result = i.next(); while (i.hasNext()) { T t = i.next(); if (t.compareTo(result) > 0) result = t; } return result; }