5 Important Points about Java Generics
Generics allows a type or method to operate on objects of various types while providing compile-time type safety, making Java a fully statically typed language.
Join the DZone community and get the full member experience.
Join For FreeGenerics are one of the most controversial Java language features. Generics allows a type or method to operate on objects of various types while providing compile-time type safety, making Java a fully statically typed language. In this article, I am going to talk about five things that every Java developer should know about Generics.
Generics are implemented using Type Erasure
In Java a class or an interface can be declared to define one or more type parameters and those type parameters should be provided at the time of object construction. For example,Generics does not support sub-typing
Generics does not support sub-typing which means that List is not considered to be a sub-type of List, where S is a subtype of T. For example, You can't create Generic Arrays
You can't create generic arrays as shown below because arrays carry runtime type information about the type of elements . Arrays uses this information at runtime to check the type of the object it contains and will throw ArrayStoreException if the type does not match. But with Generics type information gets erased and the array store check will succeed in cases where it should fail. Use of wildcards with extends or super to increase API flexibility
There are times that you need to work not only with T but also with sub types of T. For example, the addAll method in the Collection interface which adds all the elements in the specified collection to the collection on which it is called. addAll method has the signature Use of Multiple Bounds
Multiple bounds is one of the generics features which most developer do not know. It allows a type variable or wildcard to have multiple bounds. For example, if you to define constraint such as that the type should be a Number and it should implement Comparable.
List<Long> list = new ArrayList<Long>();list.add(Long.valueOf(1));list.add(Long.valueOf(2));
List<Number> numbers = new ArrayList<Integer>(); // will not compile
List<Long> list = new ArrayList<Long>();list.add(Long.valueOf(1));list.add(Long.valueOf(2));List<Number> numbers = list; // this will not compilenumbers.add(Double.valueOf(3.14));
T[] arr = new T[10];// this code will not compile
List<Integer>[] array = new List<Integer>[10]; // does not compile
List<Integer>[] ints = new List<Integer>[10]; // does not compileObject[] objs = ints;List<Double> doubles = new ArrayList<Double>();doubles.add(Double.valueOf(12.4));objs[0] = doubles; // this check should fail but it succeed
boolean addAll(Collection<? extends E> c)
List<Number> numbers = new ArrayList<Number>();ArrayList<Integer> integers = new ArrayList<Integer>();ArrayList<Long> longs = new ArrayList<Long>();ArrayList<Float> floats = new ArrayList<Float>();numbers.addAll(integers);numbers.addAll(longs);numbers.addAll(floats);
public static <T> boolean addAll(Collection<? super T> c, T... elements) ;
It proves very helpful whenever you are confused about whether you should use extends or super.
public static <T extends Number & Comparable<? super T>> int compareNumbers(T t1, T t2){return t1.compareTo(t2);}
public static <T extends String & Number > int compareNumbers(T t1, T t2) // does not work..can't have two classespublic static <T extends Comparable<? super T> & Number > int compareNumbers(T t1, T t2) // does not work..public static <T extends CharSequence & Comparable<T>> int compareNumbers(T t1, T t2)// works..multiple interfaces
Opinions expressed by DZone contributors are their own.
Comments