EFFECTIVE
JAVA
Roshan Deniyage
Axiohelix Co. Ltd
02/09/2010
Generics
Don’t use raw types in new codes
 Generics are a facility of generic programming that was added to the Java 
programming language in 2004 as part of J2SE 5.0.
 They allow "a type or method to operate on objects of various types while 
providing compile-time type safety.
What is Generics ?
public static void main(String args[]) {
List dataList = new ArrayList();
dataList.add("1");
dataList.add("test");
dataList.add(new Integer(10));
Integer value = (Integer) dataList.get(0);
}
Why need generics?
 This is old type of code which used before java SE5.
 Can you figure out the problem of this code??
// Throws ClassCastException
 So, programmers’ mistake can’t discover as soon as possible after they are 
made.  Exception can be thrown at run time.
 Therefore, a concept called generics was introduced to the java language in 
java SE5.
A class or interface whose declaration has one or more type parameters is a 
generic class or generic interface. (generic type)
Ex :
Generic interface declaration
public interface List<E> extends Collection<E> {
// Bulk of code is emitted
}
Generic class declaration
public class ArrayList<E> extends AbstractList<E> implements List<E>, Random-access,
Cloneable, java.io.Serializable {
// Bulk of code is emitted
}
Generic Types
Client Code
1.List<String> dataListWithGenerics = new ArrayList<String>();
// parameterized List
2.   List dataListWithoutGenerics = new ArrayList(); // raw type List
Both declarations are legal.
So, what is the difference ?
Number 1 is parameterized type representing List whose element type is 
“String”.
Number 2 is raw type representing List whose element type can be any type. 
(behave same as List representation before generic is added to the language)
Generic Types
public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
Set<E> result = new HashSet<E>(s1);
result.addAll(s2);
return result;
}
This is discussed in Item 27
Generic Methods
Compiler use process called erasure.
(It erase all the generic type information at compile time)
 All the type information betweeen angle brackets is thrown out.
 All remaining uses of type variables are replaced by the upper bound of the type variable
(usually Object)
 Whenever the resulting code isn’t type-correct, a cast to the appropriate type is inserted
How generics work?
How generics work?
public String loophole(Integer x) {
List<String> ys = new LinkedList<String>();
List xs = ys;
xs.add(x); // compile-time unchecked warning
return ys.iterator().next();
}
public String loophole(Integer x) {
List ys = new LinkedList;
List xs = ys;
xs.add(x);
return (String) ys.iterator().next(); // run time error
}
Compiler change the source as follows
Let’s take an example :
If client code with raw type is as follows,
private final Collection stamps = new ArrayList() ;
stamps.add(new Coin());
Later if stamps is accessed as follows,
for (Iterator i = stamps.iterator(); i.hasNext(); ) {
Stamp s = (Stamp) i.next();
... // Do something with the stamp
}
// Accidently added code
What is the difference between the raw type
and parameterized type
// Throws ClassCastException
private final Collection<Stamp> stamps = new ArrayList<Stamp>() ;
stamps.add(new Coin());
for (Iterator i = stamps.iterator(); i.hasNext(); ) {
Stamp s = i.next();
... // Do something with the stamp
}
// Compile error will arise when you attempt to insert
Coin object to the collection
What happened if you replace raw type with
generics?
// No need to explicit casting, compiler will do that for you
Other benefits
// for-each loop over a parameterized collection - type safe
for (Stamp s : stamps) { // No cast
... // Do something with the stamp
}
// for loop with parameterized iterator declaration - type safe
for (Iterator<Stamp> i = stamps.iterator(); i.hasNext(); ) {
Stamp s = i.next(); // No cast necessary
... // Do something with the stamp
}
 If you use raw types, you lose all the safety and expressiveness
benefits of generics.
 Language provide raw types to support migration compatibility since
there are enormous amount of old codes exists.
 It had to be legal to pass instances of parameterized types to methods
that were designed for use with ordinary types, and vice versa.
 So instead of using raw types better to use parameterized types like,
 List<String>, List<Object>
 But there is a sub typing rule to consider.
 Although String is a subtype of Object List<String> is not a
subtype of List<Object>
 List<String> is a subtype of List
 List<String> is a subtype of List<?>
Note
In Item 25 these rules are discussed deeply.
Conclusion
 You lose type safety if you use a raw type like List, but not if you use
a parameterized type like List<Object>
Ex :
// Uses raw type (List) - fails at runtime
public static void main(String[] args) {
List<String> strings = new ArrayList<String>();
unsafeAdd(strings, new Integer(42));
String s = strings.get(0); // Compiler-generated cast
}
private static void unsafeAdd(List list, Object o) {
list.add(o); // you get a warning here since this is raw type
}
Best way to use
private static void unsafeAdd(List<Object> list, Object o) {
list.add(o);
}
 So, you will get a compile time error when try to add new Integer(42) object
to the list. So error can be detected earlier, not at run time.
 Anyway the above code doesn’t work, so working version of this code need
to be as follows,
Best way to use
Suggestion
public static void main(String[] args) {
List<String> strings = new ArrayList<String>();
safeAdd(strings, new Integer(42)); // compile time error detection
String s = strings.get(0);
}
private static <E> void safeAdd(List<E> list, E e) {
list.add(e);
}
Best way to use
// Unbounded wildcard type - type safe and flexible
int numElementsInCommon(Set<?> s1, Set<?> s2) {
int result = 0;
for (Object o1 : s1) {
if (s2.contains(o1))
result++;
}
return result;
}
When read data from a source
 Actual type of the ? will be detected by the compiler using a technique called
wild card detection.
 This will be explained in Item-27 clearly.
Benefit of using wildcard
 You can’t put any element (other than null) into a Collection<?>
(If you use wildcard declaration, preventing you from corrupting the
collection’s type invariant)
Limitation of the wildcard
 If need can’t put any element other than null.
 Can’t assume anything about the type of the objects that you get out.
If these restrictions are unacceptable, you can use generic methods (Item 27)
or bounded wildcard types (Item 28)
Exceptions (When you must use raw types)
1. You must use raw types in class literals
The specification does not permit the use of parameterized types in class
literals.
 List.class, String[].class, and int.class - are all legal
 List<String>.class and List<?>.class - are not legal
2. This is the preferred way to use the instanceof operator with generic
types
// Legitimate use of raw type - instanceof operator
if (o instanceof Set) { // Raw type
Set<?> m = (Set<?>) o; // Wildcard type
}
Summary
 Using raw types can lead to exceptions at runtime, so don’t use them in new
code.
 They are provided only for compatibility and interoperability with legacy code
that predates the introduction of generics.
Safe Type Declarations
Set<Object> - Parameterized type representing a set that can contain
objects of any type.
Set<?> - Wildcard type representing a set that can contain only objects
of some unknown type.
Unsafe Type Declaration
Set - Raw type
Term Example Item
Parameterized type List<String> Item 23
Actual type parameter String Item 23
Generic type List<E> Items 23, 26
Formal type parameter E Item 23
Unbounded wildcard type List<?> Item 23
Raw type List Item 23
Bounded type parameter <E extends Number> Item 26
Recursive type bound <T extends Comparable<T>> Item 27
Bounded wildcard type List<? extends Number> Item 28
Generic method static <E> List<E> asList(E[] a) Item 27
Type token String.class Item 29
Summary (Cont…) / New terms introduced
THANK YOU!

Effective Java - Generics

  • 1.
    EFFECTIVE JAVA Roshan Deniyage Axiohelix Co.Ltd 02/09/2010 Generics Don’t use raw types in new codes
  • 2.
     Generics are a facility of generic programming that was added to the Java  programming language in 2004 as part of J2SE 5.0. They allow "a type or method to operate on objects of various types while  providing compile-time type safety. What is Generics ?
  • 3.
    public static void main(String args[]) { List dataList = new ArrayList(); dataList.add("1"); dataList.add("test"); dataList.add(new Integer(10)); Integer value = (Integer) dataList.get(0); } Why need generics? This is old type of code which used before java SE5.  Can you figure out the problem of this code?? // Throws ClassCastException  So, programmers’ mistake can’t discover as soon as possible after they are  made.  Exception can be thrown at run time.  Therefore, a concept called generics was introduced to the java language in  java SE5.
  • 4.
    A class or interface whose declaration has one or more type parameters is a  genericclass or generic interface. (generic type) Ex : Generic interface declaration public interface List<E> extends Collection<E> { // Bulk of code is emitted } Generic class declaration public class ArrayList<E> extends AbstractList<E> implements List<E>, Random-access, Cloneable, java.io.Serializable { // Bulk of code is emitted } Generic Types
  • 5.
    Client Code 1.List<String> dataListWithGenerics = new ArrayList<String>(); // parameterizedList 2.   List dataListWithoutGenerics = new ArrayList(); // raw type List Both declarations are legal. So, what is the difference ? Number 1 is parameterized type representing List whose element type is  “String”. Number 2 is raw type representing List whose element type can be any type.  (behave same as List representation before generic is added to the language) Generic Types
  • 6.
    public static <E>Set<E> union(Set<E> s1, Set<E> s2) { Set<E> result = new HashSet<E>(s1); result.addAll(s2); return result; } This is discussed in Item 27 Generic Methods
  • 7.
    Compiler use processcalled erasure. (It erase all the generic type information at compile time)  All the type information betweeen angle brackets is thrown out.  All remaining uses of type variables are replaced by the upper bound of the type variable (usually Object)  Whenever the resulting code isn’t type-correct, a cast to the appropriate type is inserted How generics work?
  • 8.
    How generics work? publicString loophole(Integer x) { List<String> ys = new LinkedList<String>(); List xs = ys; xs.add(x); // compile-time unchecked warning return ys.iterator().next(); } public String loophole(Integer x) { List ys = new LinkedList; List xs = ys; xs.add(x); return (String) ys.iterator().next(); // run time error } Compiler change the source as follows
  • 9.
    Let’s take anexample : If client code with raw type is as follows, private final Collection stamps = new ArrayList() ; stamps.add(new Coin()); Later if stamps is accessed as follows, for (Iterator i = stamps.iterator(); i.hasNext(); ) { Stamp s = (Stamp) i.next(); ... // Do something with the stamp } // Accidently added code What is the difference between the raw type and parameterized type // Throws ClassCastException
  • 10.
    private final Collection<Stamp>stamps = new ArrayList<Stamp>() ; stamps.add(new Coin()); for (Iterator i = stamps.iterator(); i.hasNext(); ) { Stamp s = i.next(); ... // Do something with the stamp } // Compile error will arise when you attempt to insert Coin object to the collection What happened if you replace raw type with generics? // No need to explicit casting, compiler will do that for you Other benefits // for-each loop over a parameterized collection - type safe for (Stamp s : stamps) { // No cast ... // Do something with the stamp } // for loop with parameterized iterator declaration - type safe for (Iterator<Stamp> i = stamps.iterator(); i.hasNext(); ) { Stamp s = i.next(); // No cast necessary ... // Do something with the stamp }
  • 11.
     If youuse raw types, you lose all the safety and expressiveness benefits of generics.  Language provide raw types to support migration compatibility since there are enormous amount of old codes exists.  It had to be legal to pass instances of parameterized types to methods that were designed for use with ordinary types, and vice versa.  So instead of using raw types better to use parameterized types like,  List<String>, List<Object>  But there is a sub typing rule to consider.  Although String is a subtype of Object List<String> is not a subtype of List<Object>  List<String> is a subtype of List  List<String> is a subtype of List<?> Note In Item 25 these rules are discussed deeply. Conclusion
  • 12.
     You losetype safety if you use a raw type like List, but not if you use a parameterized type like List<Object> Ex : // Uses raw type (List) - fails at runtime public static void main(String[] args) { List<String> strings = new ArrayList<String>(); unsafeAdd(strings, new Integer(42)); String s = strings.get(0); // Compiler-generated cast } private static void unsafeAdd(List list, Object o) { list.add(o); // you get a warning here since this is raw type } Best way to use
  • 13.
    private static voidunsafeAdd(List<Object> list, Object o) { list.add(o); }  So, you will get a compile time error when try to add new Integer(42) object to the list. So error can be detected earlier, not at run time.  Anyway the above code doesn’t work, so working version of this code need to be as follows, Best way to use
  • 14.
    Suggestion public static voidmain(String[] args) { List<String> strings = new ArrayList<String>(); safeAdd(strings, new Integer(42)); // compile time error detection String s = strings.get(0); } private static <E> void safeAdd(List<E> list, E e) { list.add(e); } Best way to use
  • 15.
    // Unbounded wildcardtype - type safe and flexible int numElementsInCommon(Set<?> s1, Set<?> s2) { int result = 0; for (Object o1 : s1) { if (s2.contains(o1)) result++; } return result; } When read data from a source  Actual type of the ? will be detected by the compiler using a technique called wild card detection.  This will be explained in Item-27 clearly.
  • 16.
    Benefit of usingwildcard  You can’t put any element (other than null) into a Collection<?> (If you use wildcard declaration, preventing you from corrupting the collection’s type invariant) Limitation of the wildcard  If need can’t put any element other than null.  Can’t assume anything about the type of the objects that you get out. If these restrictions are unacceptable, you can use generic methods (Item 27) or bounded wildcard types (Item 28)
  • 17.
    Exceptions (When youmust use raw types) 1. You must use raw types in class literals The specification does not permit the use of parameterized types in class literals.  List.class, String[].class, and int.class - are all legal  List<String>.class and List<?>.class - are not legal 2. This is the preferred way to use the instanceof operator with generic types // Legitimate use of raw type - instanceof operator if (o instanceof Set) { // Raw type Set<?> m = (Set<?>) o; // Wildcard type }
  • 18.
    Summary  Using rawtypes can lead to exceptions at runtime, so don’t use them in new code.  They are provided only for compatibility and interoperability with legacy code that predates the introduction of generics. Safe Type Declarations Set<Object> - Parameterized type representing a set that can contain objects of any type. Set<?> - Wildcard type representing a set that can contain only objects of some unknown type. Unsafe Type Declaration Set - Raw type
  • 19.
    Term Example Item Parameterizedtype List<String> Item 23 Actual type parameter String Item 23 Generic type List<E> Items 23, 26 Formal type parameter E Item 23 Unbounded wildcard type List<?> Item 23 Raw type List Item 23 Bounded type parameter <E extends Number> Item 26 Recursive type bound <T extends Comparable<T>> Item 27 Bounded wildcard type List<? extends Number> Item 28 Generic method static <E> List<E> asList(E[] a) Item 27 Type token String.class Item 29 Summary (Cont…) / New terms introduced
  • 20.