The beauty of using Generics in Java
Our pride as senior developers is succinct and accurate code, an algorithm that works and is not redundant. I used to adore complex-looking code back when I was first learning to code. But I couldn’t make out what was going on.
checkedSortedMap​(SortedMap<K,​V> m, Class<K> keyType, Class<V> valueType)
Writing Generic Algorithms
Some algorithms can be used for a variety of tasks. For example, suppose you wish to do a binary search across a large range of datatypes. You’d have to repeat the code as many times as the implementation required without generics.
public int runBinarySearchRecursively(
int[] sortedArray, int key, int low, int high) {
int middle = low + ((high - low) / 2);
if (high < low) {
return -1;
}
if (key == sortedArray[middle]) {
return middle;
} else if (key < sortedArray[middle]) {
return runBinarySearchRecursively(
sortedArray, key, low, middle - 1);
} else {
return runBinarySearchRecursively(
sortedArray, key, middle + 1, high);
}
}
This code will only work with a list of sorted integers… what if you wanted it to also work with floating points or even variable characters?
public class BinarySearch<T extends Comparable<T>> {
public int search(Comparable<T> v) {
int low = 0;
int high = a.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
T midVal = a[mid];
int result = v.compareTo(midVal);
if (result < 0) {
high = mid - 1;
} else if (result > 0) {
low = mid + 1;
} else {
return mid;
}
}
return -1;
}
Stronger type checks at compile time.
A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. Fixing compile-time errors is easier than fixing runtime errors, which can be difficult to find.
Limination of casts.
//Without Generics
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);
//When re-written to use generics, the code does not require casting:
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0); // no cast
In conclusion
When compiling a class or interface that extends a parameterized class or implements a parameterized interface, the compiler may need to create a synthetic method, which is called a bridge method, as part of the type erasure process. You normally don’t need to worry about bridge methods, but you might be puzzled if one appears in a stack trace.