import java.util.*; // javac -source 1.5 Generics.java // Will compile with warnings // javac -source 1.5 -Xlint Generics.java // Generics allows you to have type safe collections // Generics is a compile time feature and not runtime so at runtime there is type erasure public class Generics { public static void generics() { LinkedList fooList = new LinkedList(); fooList.add(new Integer(1)); // lint warning about unchecked add LinkedList stringList = new LinkedList(); // LinkedList is called base type // String is called parameter type // primitive generics not allowed //LinkedList intList = new LinkedList(); stringList.add("foo"); // The line below will throw compilation error //stringList.add(new Integer(1)); // Old Style iterator code will give compilation error for stringList for (Iterator i = stringList.iterator(); i.hasNext();) { String s = i.next(); System.out.println(s); } printStrings(stringList); oldStyle(stringList); // can still do old style // gives warning if compiled with -Xlint try { for (Iterator i = fooList.iterator(); i.hasNext();) { String s = i.next(); // ClasscastException at runtime System.out.println(s); } } catch (ClassCastException e) { e.printStackTrace(); } LinkedList intList = new LinkedList(); intList.add(new Integer(1)); intList.add(2); // autoboxing does automatic conversion to primitive types printAny(intList); List intList2 = intList; // inhertiance rules are for base type and not parameter type // class Integer extends Number //Not Allowed for parameter type //List numberList = intList; // to prevent numberList.add(1.2) // can break type safety by casting and by reflection LinkedList numberList = intList; numberList.add(1.2); // allowed generated lint warning Map> map = new HashMap>(); List objList1 = new LinkedList(); objList1.add(1); // lint warning that collection is not type safe // for a collection which hold differnt objects so that you don't get lint warnings List objList2 = new LinkedList(); MyList myList = new MyList(); myList.add(101); System.out.println(myList.first()); // Illegal //MyList2 f; } public static void printStrings(List stringList) { for (Iterator i = stringList.iterator(); i.hasNext();) { String s = i.next(); System.out.println(s); } } // type wildcards // method that takes a List of any parameter type // can't do this as List as it won't take List // method is read only public static void printAny(List anyList) { // The line below will not compile as Java does not the type of the collection at compile time //anyList.add(new Integer(1)); for (Iterator i = anyList.iterator(); i.hasNext();) { System.out.println(i.next().toString()); } } // restrict wildcards public static void printAnyNumber(List anyList) { // The line below will not compile as Java does not the type of the collection at compile time //anyList.add(new Integer(1)); for (Iterator i = anyList.iterator(); i.hasNext();) { System.out.println(i.next().toString()); } } public static List getStringList() { LinkedList foo = new LinkedList(); foo.add("foo"); return foo; } public static void oldStyle(List fooList) {} // should work but doesnt //public static int staticSize(MyList list) //{ // return list.size(); //} public static void main(String[] args) { generics(); } } class MyList { public MyList() { list = new LinkedList(); } public int size() { return list.size(); } public void add(T obj) { list.add(obj); } public T first() { return list.get(0); } private LinkedList list; // not allowed with statics // private static LinkedList list2; } // Restricting parameterized type to objects that are child of Number class MyList2 extends MyList {}