Introduction to generics in Java Java 05.02.2016

Parameterized types (generics) are useful because they enable you to create classes, interfaces, and methods in which the type of data upon which they operate is specified as a parameter. A class, interface, or method that operates on a type parameter is called generic.

A principal advantage of generic code is that it will automatically work with the type of data passed to its type parameter. Many algorithms are logically the same no matter what type of data they are being applied to. For example, a Quicksort is the same whether it is sorting items of type Integer, String, Object, or Thread. With generics, you can define an algorithm once, independently of any specific type of data, and then apply that algorithm to a wide variety of data types without any additional effort.

By using generic notation, you get help from Java compiler, which does not allow you to use objects of the "wrong" types that don’t match the declaration. In other words, you can catch improper data types earlier, during the compilation phase. Getting an error during compilation is better than getting runtime cast exceptions.

Consider the ArrayList which is a storage that can hold pretty much any object. But if you add the parameterized type Product in angle brackets (ArrayList<Product>) to the declaration of the basket collection, any attempt to place an Man object there generates compiler error.

List<Product> basket = new ArrayList<>();
Product milk = new Product("Milk", 12.47);
basket.add(milk);
Product bred = new Product("Bread", 7.56);
basket.add(bread);

for (Product prod: basket){
    prod.doSomething();
}

If you’ll be creating your own class for storing objects, you can use any letter(s) in angle brackets to declare that your class will use parameterized types. You can use any letters to represent parameterized types, but traditionally developers use <E> for element, <T> for type, <K> for keys, <V> for value, and so on. The letter is replaced by a concrete type during concrete variable declaration.

Example with one parameterized type which shows how to get object of parameterized type and print it class name. Note, generics work only with reference types (Integer, Double, etc).

class Price<T> {
    T val;
    Price(T val) {
        this.val = val;
    }
    T getValue() {
        return val;
    }
    void getType() {
        System.out.println(val.getClass().getName());
    }
}

class PriceDemo {
    public static void main(String args[]) {
        // Demo for Integer type
        Price<Integer> iPrice = new Price<>(48);
        // or Price<Integer> iPrice = new Price<Integer>(48);
        iPrice.getType();
        int v = iPrice.getValue();
        System.out.println(v);

        System.out.println();

        // Demo for String type
        Price<String> sPrice = new Price<>("forty eight");
        // or Price<String> sPrice = new Price<String>("forty eight");
        sPrice.getType();
        String s = sPrice.getValue();
        System.out.println(s);
    }
}