Download presentation
Presentation is loading. Please wait.
1
Java Generics
2
Basic 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);
3
Line (1.1) is possible because
How It Can Be Misused Line (1.1) is possible because myIntList doesn’t know what kind of object it is supposed to store Line (3.1) succeeds at compile time because at compile time the list doesn’t 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
4
Generic 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, List<Integer> is also an Interface that LinkedList<Integer> implements. Now myIntList “knows” it will only store Integer objects so the cast on line (6) becomes unnecessary. List<Integer> myIntList = new LinkedList<Integer>(); // 4 myIntList.add(new Integer(0)); // 5 Integer x = myIntList.iterator().next(); // 6
5
Generic 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). You’ve 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
6
How does lastIndexOf() do this?
ArrayList 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 <Integer> al = new Arraylist<Integer>(100); // 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
7
List Iterators (1): ArrayList<E> implements List<E> which extends Iterable<E>. Things which implement Iterable<E> 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: ArrayList<E>) int lastIndexOf(E e) { int temp = -1, index = -1; for (E next : this) { index++; if (next.equals(e)) temp = index; } return temp;
8
This type of for loop hides exactly how Iterators work
List 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; Iterator<E> 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;
9
The Interfaces In Question:
These two snippets show a small portion of the List<E> interface and almost the entire Iterator<E> interface. Remember, each time you see <E> you are looking at a formal parameter type declaration. When you see something like <Integer> 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 List<E> { void add(E x); Iterator<E> iterator(); } public interface Iterator<E> { E next(); boolean hasNext();
10
How Does This Differ From C++?
In C++ each parameterized collection like List<Integer> will have its own source and object code. In Java “one size fits all”. There is only one .class file for all LinkedList<E> code.
11
Generics and Subtyping:
List<String> ls = new ArrayList<String>(); // 7 List<Object> lo = ls; // 8 We can assign an ArrayList reference to a List variable. Can we assign an ArrayList<Integer> reference to a List<Object> 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!
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.