Title: Java Generics
1Java Generics
2Basic Concept Without Generics
- The cast on line (3) is needed because the
signature of List.add() is - So the new Integer object forgets its type when
added to the list and needs to be reminded
recall in line (3). - Obviously the Integer object still sits in the
list even though our program also has a reference
to it.
List myIntList new LinkedList() //
1 myIntList.add(new Integer(0)) // 2 Integer x
(Integer) myIntList.iterator().next() // 3
public void add(Object o)
3How It Can Be Misused
- Line (1.1) is possible because
- myIntList doesnt know what kind of object it is
supposed to store - Line (3.1) succeeds at compile time because
- at compile time the list doesnt actually exist
so the compiler takes on faith that this cast
will be ok. - Line (3.1) fails at run time because the object
being retrieved is a String and not an Integer so
this cast is illegal.
myIntList.add(123) // 1.1 . . . Integer I
(Integer) myIntList.iterator().next() // 3.1
4Generic Alternative
- The alternative is to add to the myIntList
declaration a contract that you will only put
Integer objects into the list. - This is done by adding a type parameter to the
data type declaration and construction. - Just like List is an Interface that LinkedList
implements, ListltIntegergt is also an Interface
that LinkedListltIntegergt implements. - Now myIntList knows it will only store Integer
objects so the cast on line (6) becomes
unnecessary.
ListltIntegergt myIntList new LinkedListltIntegergt(
) // 4 myIntList.add(new Integer(0)) //
5 Integer x myIntList.iterator().next() // 6
5Generic Alternative (2)
- Now, the attempt to assign a String to the list
on line (4.1) fails at compile time (and not
later, at run time). - Youve signed a contract to only put Integer
objects in there and you are clearly breaking the
contract. - In general, failure at compile time is better
than failure at run time. - This difference between compile vs run time error
detection means we really have done more than
move the clutter around.
myIntList.add(123) // 4.1 fails at compile
time
6ArrayList Example
- The two Integer objects I created are different
objects but are the same when compared with
Integer.equals(). - So lastIndexOf() finds the first object by
comparing the second to it using
Integer.equals(). - How does lastIndexOf() do this?
ArrayList ltIntegergt al new ArraylistltIntegergt(10
0) // initial capacity 100 al.add(new
Integer(123) // adds a new element at the
beginning of the list
// succeeds because Integer
has the correct constructor al.add(10,new
Integer(4)) // adds a new Integer object at
location 10. int loc al.lastIndexOf(new
Integer(4)) // returns 10 to loc
7List Iterators (1)
- ArrayListltEgt implements ListltEgt which extends
IterableltEgt. - Things which implement IterableltEgt have an
enhanced version of the standard for-loop. - Iterators let you walk through the elements of a
list without worrying about indexing 0, 1, 2,
for (E next ArrayListltEgt)
int lastIndexOf(E e) int temp -1, index
-1 for (E next this) index
if (next.equals(e)) temp
index return temp
8List Iterators (2)
- This type of for loop hides exactly how Iterators
work - Please note no indexes anywhere in either of
these two examples.
int lastIndexOf(E e) int temp -1, index
-1 IteratorltEgt ii this.iterator() //
the iterator object is distinct
// from the
list it manipulates while(ii.hasNext()) //
hasNext() tells you if more elements exist in the
list index E f ii.next()
// next() gets a reference to the next element.
if (f.equals(e)) temp index
return temp
9The Interfaces In Question
- These two snippets show a small portion of the
ListltEgt interface and almost the entire
IteratorltEgt interface. - Remember, each time you see ltEgt you are looking
at a formal parameter type declaration. - When you see something like ltIntegergt you are
looking at an actual parameter type declaration. - Because the latter is still only a declaration
it is still only an actual parameter type and
not an actual parameter.
public interface ListltEgt void add(E x)
IteratorltEgt iterator() public interface
IteratorltEgt E next() boolean
hasNext()
10How Does This Differ From C?
- In C each parameterized collection like
ListltIntegergt will have its own source and object
code. - In Java one size fits all. There is only one
.class file for all LinkedListltEgt code.
11Generics and Subtyping
ListltStringgt ls new ArrayListltStringgt() //
7 ListltObjectgt lo ls // 8
- We can assign an ArrayList reference to a List
variable. - Can we assign an ArrayListltIntegergt reference to
a ListltObjectgt variable? - If we could, then line 10 would fail at run time.
We are trying to avoid this. - The java compiler will object to line 8.
lo.add(new Object()) // 9 String s ls.get(0)
// 10 attempts to assign an Object to a String!