Vous êtes sur la page 1sur 37

Generics and Collection

Part 1

1
Java
Contents

1 Motivation behind generics


2 Creating type-safe collections
3 Type Erasure
4 Mixing generics and legacy code
5 Consequences of mixing code
6 Generics and polymorphism
7 Wild card characters
8 Y<? extends X>
9 Y<? super X>
10 Y<?>
11 Revisit :converting Collection into arrays
2
Java
Contents

12 Creating your own generic class and generic methods


13 Identifying a generic class
14 Code snippet of List interface
15 User defined generic class
16 Defined generic method
17 Restricting to certain types
18 Summary of valid and invalid generic assignments

3
Java
Know
• What generics is about
• Type Erasure
• How to creating generic classes

4
Java
Be able to
• Use generics
• Create your own generic class

5
Java
Motivation behind generics
import java.util.*;
class Test{
public static void main(String[] s){
ArrayList a= new ArrayList();
a.add(1);
a.add("Mary"); Allows you to add any kind of object
a.add(1.78);
for(Object o:a) Primary reason why generics came in
System.out.println(o);
} } Explicit cast required
Integer i=(Integer)a.get(1);
6
Example 1 Java
Creating type-safe collections
import java.util.*;
class Test{
public static void main(String[] s){
ArrayList<Integer> a= new
ArrayList<Integer>();
a.add(1);
a.add(2); Allows you to add only integers
a.add(3);
unboxing
for(int o:a)
System.out.println(o);
} } int i=((Integer)a.get(1)).intValue();
Example 2 7
Java
Is an instance of ArrayList<Object>
same as instance of ArrayList ?

In terms of what both the


instances hold-they are
same, but the compiler
treats generics very
differently from non-generic
collection. Meaning
ArrayList<Object> and
ArrayList are not exactly
same. We will see this…
Type Erasure

• Generics are implemented by type erasure:


generic type information is present only at
compile time, after which it is erased by the
compiler.
• Which means that the ArrayList<Integer>
becomes ArrayList at runtime.

9
Java
Mixing generics and legacy
code
Legal Code:
• ArrayList<Integer> a= new ArrayList();
• ArrayList a= new ArrayList<Integer>();
• List<Integer> a= new ArrayList();
• List a= new ArrayList<Integer>();
• List<Integer> a= new
ArrayList<Integer>();

10
Java
The compiler allows
this so that the legacy
code which was
written in the good old
java days also works
with generics. At first it
may sound good. But
there are some
undesirable
consequences which
we must be aware of.
An example of such a
consequence is in the
next slide. 11
Java
Consequences of mixing code
import java.util.*;
class Test{
public static void main(String[] s){
ArrayList a=new ArrayList();
a.add(1);a.add(1.1);
ArrayList<Integer> b=a;
java.lang.ClassCastException
for(Integer i:b) : java.lang.Double at runtime

System.out.println(i);}}
12
Example 3 Java
Another such situation would be :
List l= new ArrayList<Integer>();
l.add(“AbC”);
•Perfectly valid code! No compile-time or runtime
errors. Only a warning is generated.
•Both the examples lead to incorrect situations.That
is the reason why a warning is generated by the
compiler when you add or manipulate the elements
using non-type safe collections.

13
Java
Generics and polymorphism

• List<Integer> a= new
ArrayList<Integer>();
• List<Number> a= new
ArrayList<Integer>();

WHY ?
14
Java
•Hypothesis:List<Number> a= new
ArrayList<Integer>(); is valid.
Assume the following code snippet:
ArrayList<Integer> a= new
ArrayList<Integer>();
a.add(1);
Valid as per hypothesis
m(a);}
static void m(List<Number> n){
Oops! we just added a double
Double d=3.4; into an Integer collection
n.add(d); ..} Number

Integer Double
15
Java
•Could the compiler have generated a warning?
• Assuming that hypothesis is correct, every part of
the code is legal. Answer is NO.
•Could the runtime system know?
• NO. Runtime system does not have any
information about type of collection (type erasure).
For the runtime system List<Number> is just List
and ArrayList<Integer> is just ArrayList.
•Conclusion: The hypothesis is incorrect.
•List<Number> a= new ArrayList<Integer>(); is
not valid.

16
Java
How was it alright with arrays?
Number n[]= new Integer[3]; is Ok
But
ArrayList<Number> n= new
ArrayList<Integer> is not ok.

Let us compile and execute


a code involving arrays
before I comment on it.

17
Java
class Test{
public static void main(String[] s){
Number n[]= new Integer[5];
n[0]=1;
n[1]=2;
m(n); legal }
static void m(Number[] l){
l[3]=3.4; }}
•No errors at compile time.
•Runtime error:java.lang.ArrayStoreException:
java.lang.Double Example 4
18
Java
Compare the two cases
(array and collection) and
try to answer how they are
different! Are you telling us that a
collection can either hold any
type of data or strictly only
single type of data- Integer
means only Integers, Number
means only numbers – good
bye to polymorphism !

No ! Java designers
did find a way to
work around this
problem. Go ahead.
19
Java
Wild card characters
•Y<? extends X>
•Y<? super X>
•Y<?>

where Y is any collection class that


implements Collection interface or Map
(we are concentrating only on collection with
generics here )
and
X is any class or an interface.

20
Java
Y<? extends X>
• ArrayList<? extends Number> l= new
ArrayList<Integer>();
• ArrayList<? extends Number> references can be
used to hold Number or any subclass of Number
and cannot be used for adding elements.
• Syntax:
AnyCollectionClass<? extends
AnyClassorInterface>
• Needless to state the above syntax is valid only on
the left-hand side of the assignment.

21
Java
import java.util.*;
class Test{
public static void main(String[] s){
ArrayList<Integer> l=new
ArrayList<Integer>();
l.add(1);
l.add(2);
ArrayList<? extends Number> m= l;
m.add(1); Generates compilation error
System.out.println(m.get(1));
Example 5
}} 22
Java
Y<? super X>
• ArrayList<? super Integer> reference can hold
any elements of type Integer or super class of
Integer and allows all the operations including
add.
ArrayList<? super Integer> l=new
ArrayList<Integer>();
l.add(1);l.add(2); Valid code

ArrayList<? super Number> m=


new ArrayList<Integer>();
is invalid. You know why?

23
Java
Y<?>
• A reference of ArrayList<?> can hold any type of
Object but cannot be used for adding elements.
• Actually Y<?> is the short form of
<? extends Object>
ArrayList<Integer> l=new ArrayList<Integer>();
l.add(1);
l.add(2);
ArrayList<?> m=l;
m.add(1);
System.out.println(m.get(1));
24
Java
Revisit :converting Collection into
arrays
• In Collection interface: From Collection into array
Object[] toArray()
<T> T[] toArray(T[] a)
• The runtime type of the returned array is that of the
specified array.
• If the collection fits in the specified array, it is
returned therein. Otherwise, a new array is
allocated with the runtime type of the specified
array and the size of this collection.

25
Java
Creating your own
generic class and
generic methods

26
Java
Identifying a generic class
•The method signature of a class tells us if the class
uses generics.
•Example: List methods:
boolean add(E o)
E remove(int index)
Formal type parameter
•Invocation: List<Integer>

Actual type parameter

27
Java
Code snippet of List interface
public interface List<E> extends Collection<E> {
boolean add(E o);
boolean remove(Object o);…}
• The type parameter can be used anywhere in the
code where class is used.
• The letter ‘E’ ( or ‘T’) is just a convention. Any valid
java identifier could be used in place of E or T.
Recommendation is to use a single character in
upper case.

28
Java
So multiple copies of same
class are created when we
execute the code that has the
actual parameter

Oh no! remember ‘type erasure’- the


runtime system does not have any
clue that you used generics. The
compiler simply replaces all the E
with the actual type you specified in
the code and then compiles. Not even
one extra file is generated .

29
Java
User defined generic class
class Rack<T>{ Specify the symbol that
int rackNo; the class will use to
identify to generic type.
ArrayList<T> items;
Rack(){ items= new ArrayList<T>(); }
void add(T t){items.add(t);}
void display(){
for(T b:items){
System.out.println(b);}} }
Example 6 30
Java
class Book{
int id;
String title;
Book(int id, String title){
this.id=id;
this.title=title; }
public String toString(){
return"Id:" +id+ " Title: "+title ; }
}
31
Java
class BookRack{
public static void main(String[] s){
Book b1= new Book(1,"Application Development
with WSAD");
Book b2= new Book(2,"UML Best Practices");
Rack<Book> bookRack= new Rack<Book>();
bookRack.add(b1);
Replaces T in Rack class
bookRack.add(b2);
bookRack.display();
}}
32
Java
Defined generic method
class Test1{
public static <E> Rack<E> makeRack(E
t) {
Rack<E> rack= new Rack<E>();
rack.add(t); Tell your method to use
symbol E for generic type
return rack; }
public static void main(String[] s){
Book b1= new Book(1,"Application
Development with WSAD");
Rack<Book> bookRack= makeRack(b1);
}} 33
Java
Restricting to certain types
class Test2{
public static <E extends Book>
Rack<E> makeRack(E t) {
Rack<E> rack= new Rack<E>();
rack.add(t);return rack;}
public static void main(String[] s){
Book b1= new Book(1,"Application
Development with WSAD");
Rack<Book> bookRack= makeRack(b1);
}}
34
Java
But if we try to add CD:
Rack<CD> bRack= makeRack(new CD());

we get the following compilation error:

Test.java:13: <E>makeRack(E) in Test


cannot be applied to (CD)
Rack<CD> bRack= makeRack(new CD());
^
Note: Compiler does Generic arrays.  T[] t= new T[]; gives
compiler error!

35
Java
Summary of valid and invalid
generic assignments
• List<Integer> a= new ArrayList<Integer>() ;//ok
• ArrayList<Number> b= new ArrayList<Integer>();
//not ok

• ArrayList<?> c= new ArrayList<Integer> ();


• ArrayList<Object>= new ArrayList<Integer> ();
//not ok
• ArrayList<? extends Number > d= new
ArrayList<Integer> ();//ok
• ArrayList<? extends Integer > e= new
ArrayList<Integer>(); //ok
• ArrayList<? extends Integer > f= new
ArrayList<Double>(); //not ok 36
Java
• ArrayList<? super Integer > g= new
ArrayList<Object> ();//ok
• ArrayList<? super Integer > h= new
ArrayList<Integer> ();//ok
• ArrayList<? super Integer > i= new
ArrayList<Double> ();//not ok
• ArrayList<?> a= ref holding ArrayList<? super
Integer > //ok
• ArrayList<? >b=ref holding ArrayList<? extends
Number > //ok
• ArrayList<? >c=ref holding ArrayList<? > //ok
• ArrayList<Number>= ref holding ArrayList<?
extends Number >//not ok
37
Java

Vous aimerez peut-être aussi