The beauty of using Generics in Java

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.

×