CompSci 230 S2 2015 Software Construction Generics Agenda & Reading  Topics:      Introduction Fundamentals of generic types Generics & Subtyping Type wildcards Reading  The Java Tutorial:  Generics.

Download Report

Transcript CompSci 230 S2 2015 Software Construction Generics Agenda & Reading  Topics:      Introduction Fundamentals of generic types Generics & Subtyping Type wildcards Reading  The Java Tutorial:  Generics.

CompSci 230 S2 2015
Software Construction
Generics
Agenda & Reading

Topics:





Introduction
Fundamentals of generic types
Generics & Subtyping
Type wildcards
Reading

The Java Tutorial:

2
Generics
09
What Are Generics?



3
Generics abstract over Types
Classes, Interfaces and Methods can be Parameterized by
Types
Generics provide increased readability and type safety
09
Item
Example:
public class Item {
protected String title;
public Item(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
Book
Movie
Priced
<<interface>
>
CD
Shirt
public interface Priced {
public double getPrice();
}
public class CD extends Item implements Priced {
private double price;
...
public doublegetPrice() {...}
}
public class Movie extends Item {
private int year;
public Movie(String title, int year) {
super(title);
this.year = year;
}
...
public String toString() {
return ...
}
}
4
public class Book extends Item {
private String author;
public Book(String title, String author) {
super(title);
this.author = author;
}
...
public String toString() {
return "Book: '" + ...
}
}
09
Interface java.util.List

Java’s original specification for list data structures


This interface defines a contract for each of the operations of a list,
i.e.




5
(non-generic – Java 1.4)
What it takes in
What it returns
What the state of the list should be afterwards
Individual implementations should fulfil the contract – in whatever
way they see fit
public interface List {
public
public
public
public
public
public
public
public
public
//plus
}
boolean add(Object o);
boolean add(int i, Object);
Object remove(int i);
Object remove(Object o);
Object get(int i);
int indexOf(Object o);
boolean contains(Object o);
int size();
Iterator iterator();
others
09
Why generics?

Type Safety!

Array:




6
We must say what’s in the array
ArrayList:

Person[] people = new Person[25];
people[0] = "Sally"; // syntax error
ArrayList people = new ArrayList();
people.add("Sally");
But anything could go in the ArrayList;
We can pass in Movie, Book and CD instances as arguments to add( ) as its
formal argument type is Object
However because get( )’s return type is Object, we need to downcast the
result to the appropriate subclass
List items = new ArrayList();
items.add(new Movie("Psycho",1960));
items.add(new Book("LOTR","Toklien"));
for (int i = 0; i < items.size(); i++) {
Item item = (Item)items.get(i);
System.out.println(i+": "+item.getTitle());
}
09
Example: TestsApp
List of Items





We want items to store only objects of type Item (or its
subclasses)
What happens if it doesn't?
What exactly would happen?
Will this compile?
Will it run?
Runtime
error
7
items.add(new Movie("Psycho",1960));
items.add("Terminator");
for (int i = 0; i < items.size(); i++) {
Item item = (Item)items.get(i);
System.out.println(i+": "+item.getTitle());
}
09
Compile-time vs. Runtime errors


Moral of the story: we can’t rely on the compiler to
detect/predict all errors (although we’d like to)
What compilers can detect:


What compilers can't:


8
Syntactic/”obvious” errors, e.g: accessing an undeclared variable;
calling an undefined method; mismatching braces/brackets; assigning
a value to a variable of incompatible type
Logical errors, unexpected behaviours only observable at runtime
e.g. accessing a null field, bogus user input, nondeterministic code
Most lead to exceptions being thrown like NullPointerException,
ArrayIndexOutOfBoundsException, NumberFormatException,
ClassCastException
09
What can we do instead?

Create a specialised List for Item? NO!



Repetitive
Inefficient
Hardly scalable
public class ItemList {
private List items;
public ItemList() {
items = new ArrayList();
}
...
}
public class IntList {
private List items;
public class StringList
private List items;
public StringList () {
items = new ArrayList();
}
public IntList() {
items = new ArrayList();
}
9
public void add(Integer i) {
items.add(i);
}
...
}
{
public void add(String s) {
items.add(s);
}
...
}
09
Answer: Generics!


10
With generics, we can make List a generic type
By parameterising List with the type Item we are guaranteed
that any instance of this special List would only contain
objects of type T (or its subclasses)
09
Example: <String>

Instead of saying: List words = new ArrayList();

You'll have to say:
List<String> words = new ArrayList<String>();

Replaces runtime type checks with compile-time checks

No casting; instead of
String title = (String) words.get(i);
you use
String title = words.get(i);

11
Some classes and interfaces that have been “genericized” are:
Vector, ArrayList, LinkedList, Hashtable, HashMap, Stack,
Queue …
09
More Examples

The letter E as the type parameter for elements in generic
collections
ArrayList<String> words = new ArrayList<String>();
ArrayList<Integer> nums = new ArrayList<Integer>();

Examples:
ArrayList<String> words = new ArrayList<String>();
list1.add(new String("HA"));
list1.add(new String("HE"));;
String s1 = list1.get(0);
String s2 = list1.get(1);
System.out.println(s1 + " " + s2);
ArrayList<Integer> nums = new ArrayList<Integer>();
nums.add(new Integer(4));
nums.add(new Integer(5));
Integer i1 = nums.get(0);
Integer i2 = nums.get(1);
12
09
for-each loop


The for-each loop is used to access each successive value in a
collection of values.
Syntax:
for (Base_Type var :Collection_Object)
Statement;

Example:
ArrayList<String> words = new ArrayList<String>();
...
for (String str : words) {
System.out.println(str);
}
13
09
Example: TestGenericsApp
Generics and type safety


Good news: the compiler can help us prevent type errors
The compiler enforces the parameterised type List<Item> to
only accept and return instances of Item (or its subclasses)
COMPILE-TIME
ERROR
List<Item> genericsItems = new ArrayList<Item>();
genericsItems.add(new Movie("Psycho",1960));
genericsItems.add("Terminator");
List<Item> genericsItems = new ArrayList<Item>();
genericsItems.add(new Movie("Psycho",1960));
genericsItems.add(new Book("LOTR","Tolkien"));
genericsItems.add(new CD("Ozomatli",2.50));
for (int i = 0; i < genericsItems.size(); i++) {
Item item = genericsItems.get(i);
System.out.println(i+": "+item.getTitle());
}
14
09
Generics Vs No Generics
‘Generic type’
‘Type parameter’
/‘Type variable’
public class Arraylist<E> {
private E[] elementData;
... //stuff
public boolean add(E o) {
elementData[size++] = o;
return true;
}
public E get(int i) {
return elementData[i];
}
}
‘Non-generic type’
public class ArrayList {
private Object[] elementData;
... //stuff
public boolean add(Object o) {
elementData[size++] = o;
return true;
}
public Object get(int i) {
return elementData[i];
}
}
‘Parameterised type’
ArrayList<Item> items = new ArrayList<Item>();
‘Type argument’
15
09
Example: Comparable + Generics

Comparable Interface: java.lang.Comparable

int compareTo() returns an integer result:



Returns negative if the object it is applied to is less than the argument
Returns zero if the object it is applied to is equal to the argument
Returns positive if the object it is applied to is greater than the argument
public class Person implements Comparable {
protected String irdNumber;
...
public int compareTo(Object obj) {
if (!(obj instanceof Person)) {
throw new ClassCastException("Not a Person");
}
Person p = (Person) obj;
return irdNumber.compareTo(p.getIRD());
}
}
without Generics
16
public interface Comparable {
public int compareTo(Object obj);
}
with Generics
public class Person implements Comparable<Person>
protected String irdNumber;
...
public int compareTo(Person p) {
return irdNumber.compareTo(p.getIRD());
}
}
09
Generics & Subtyping


Is a List of String a List of Object?
Is a List of Movie a List of Item?
COMPILE-TIME
ERROR
COMPILE-TIME
ERROR

List<String> ls = new ArrayList<String>();
ls.add("Hello");
...
List<Object> lo = ls;
List<Movie> lm = new ArrayList<Movie>();
lm.add(new Movie("Psycho",1960));
...
genericsItems = lm;
If this is allowed, then we can


add items to the list of Movie by accessing genericsItems
attempt to assign an Item to a Movie object!!!
genericsItems.add(new Item("Sample"));
Movie m1 = lm.get(0);
17
ERROR
09
Generics & Subtyping

So



But


18
Movie is a subtype of Item, and G is some generic type declaration
It is not the case that G<Movie> is a subtype of G<Item>
We normally think that a List<Driver> is a List<Person> assuming
that Drive is a subtype of Person.
We will need to look at Wildcards!
09
Type wildcards

List mylist = new ArrayList();
…
printCollection(mylist);
Here’s a simple (no generics) method to print out any list (without
generics):
public static void printCollection(List c) {
for (Iterator i = c.iterator(); i.hasNext(); ) {
System.out.println(i.next());
}
}


uses unchecked or unsafe
operations.
Note: Recompile with Xlint:unchecked for details.
The above still works in Java 1.5, but now it generates warning messages
Next, here is an attempt using Generics
public static void printCollection(List<Object> c) {
for (Iterator<Object> i = c.iterator(); i.hasNext(); ) {
System.out.println(i.next());
}
}

19
But it only takes a list of Object, but it is not a supertype of all kinds of lists.
List<Item> mylist = new ArrayList<Item>();
printCollection(mylist); //ERROR
09
Type wildcards <?>

You should eliminate all errors and warnings in your final code, so
you need to tell Java that any type is acceptable:
public static void printCollection(List<?> c) {
for (Iterator<?> i = c.iterator(); i.hasNext(); ) {
System.out.println(i.next());
}
}


<?> (i.e. any type) signifies an unbounded wildcard. (pronounced “list of
unknown”)
a list whose element type matches anything = called wildcard type
List<Movie> movieList = new ArrayList<Movie>();
movieList.add(new Movie("Psycho",1960));
printCollection(movieList);
List<String> myStrlist = new ArrayList<String>();
myStrlist.add("Hello");
printCollection(myStrlist);
20
09
for-each statement

for(type var : array) {...}
or for(type var : collection) {...}
public static void printCollection(List<?> c) {
for (Object e: c) {
System.out.println(e);
}
}

Example:
List<Movie> movieList = new ArrayList<Movie>();
movieList.add(new Movie("Psycho",1960));
printCollection(movieList);
List<String> myStrlist = new ArrayList<String>();
myStrlist.add("Hello");
printCollection(myStrlist);
21
09
Subtyping in generics

Consider the following method:
public static void printItemCollection(List<Item> il) {
for (Item i: il) {
System.out.println(i.getTitle());
}
}



Item
Movie
The type rules say that the above method can only be called on
lists of exactly Item:
It cannot, for instance, be called on a List<Movie>
But, how to accept a list of any kind of item (e.g. List<Movie>,
List<Book>)
public static void printItemCollection(List<? extends Item> il) {
for (Item i: il) {
System.out.println(i.getTitle());
}
}
22
09
Bounded Wildcards

<? extends T> (i.e. any subclass of T, including T itself) signifies a
bounded wildcard
<?> (i.e. any type) signifies an unbounded wildcard
Note: <?> is equivalent to <? extends Object>




<? extends Item> => Item is the upper bound of the wildcard
Note that since wildcards denote unknown types, there are
limitations on how a wildcard variable can be used
It is now illegal to write into the list in the body of the method
Such limitations are compiler enforced


public static void printItemCollection(List<? extends Item> il) {
il.add(new Movie("Psycho",1960));
}

23
COMPILE-TIME
ERROR
It is an unknown subtype of Item. Since we don’t know what type it is, we
don’t know if it is a supertype of Movie; it might or might not be such a
supertype, so it isn’t safe to pass a Movie there.
09