generics compsci 230 s2 2015 software construction

23
Generics CompSci 230 S2 2015 Software Construction

Upload: myles-hunter

Post on 05-Jan-2016

220 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Generics CompSci 230 S2 2015 Software Construction

Generics

CompSci 230 S2 2015Software Construction

Page 2: Generics CompSci 230 S2 2015 Software Construction

2

Agenda & Reading Topics:

Introduction Fundamentals of generic types Generics & Subtyping Type wildcards

Reading The Java Tutorial:

Generics

09

Page 3: Generics CompSci 230 S2 2015 Software Construction

3

What Are Generics? Generics abstract over Types Classes, Interfaces and Methods can be

Parameterized by Types Generics provide increased readability and type

safety

09

Page 4: Generics CompSci 230 S2 2015 Software Construction

4

Example:Item

Book Movie CD

Priced<<interface

>>

Shirt

public class Item { protected String title; public Item(String title) { this.title = title; } public String getTitle() { return title; }}

public class Book extends Item { private String author; public Book(String title, String author) { super(title); this.author = author; } ... public String toString() { return "Book: '" + ... }}

public class Movie extends Item { private int year; public Movie(String title, int year) { super(title); this.year = year; } ... public String toString() { return ... }}

public class CD extends Item implements Priced { private double price; ... public doublegetPrice() {...}}

public interface Priced { public double getPrice();}

09

Page 5: Generics CompSci 230 S2 2015 Software Construction

5

Interface java.util.List Java’s original specification for list data structures

(non-generic – Java 1.4) This interface defines a contract for each of the operations

of a list, i.e. 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 boolean add(Object o); public boolean add(int i, Object); public Object remove(int i); public Object remove(Object o); public Object get(int i); public int indexOf(Object o); public boolean contains(Object o); public int size(); public Iterator iterator(); //plus others}

09

Page 6: Generics CompSci 230 S2 2015 Software Construction

6

Why generics? Type Safety!

Array: We must say what’s in the array

ArrayList: 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

Person[] people = new Person[25]; people[0] = "Sally"; // syntax error

ArrayList people = new ArrayList(); people.add("Sally");

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

Page 7: Generics CompSci 230 S2 2015 Software Construction

7

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?

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()); }

Runtime error

Example: TestsApp

09

Page 8: Generics CompSci 230 S2 2015 Software Construction

8

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: 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

What compilers can't: 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

Page 9: Generics CompSci 230 S2 2015 Software Construction

9

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 StringList { private List items;

public StringList () { items = new ArrayList(); }

public void add(String s) { items.add(s); } ...}

public class IntList { private List items;

public IntList() { items = new ArrayList(); }

public void add(Integer i) { items.add(i); } ...}

09

Page 10: Generics CompSci 230 S2 2015 Software Construction

10

Answer: Generics! 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

Page 11: Generics CompSci 230 S2 2015 Software Construction

11

Example: <String> Instead of saying: List words = new

ArrayList(); You'll have to say:

Replaces runtime type checks with compile-time checks No casting; instead of

String title = (String) words.get(i);you use

Some classes and interfaces that have been “genericized” are: Vector, ArrayList, LinkedList, Hashtable, HashMap, Stack, Queue …

List<String> words = new ArrayList<String>();

String title = words.get(i);

09

Page 12: Generics CompSci 230 S2 2015 Software Construction

12

More Examples The letter E as the type parameter for elements

in generic collections

Examples:

ArrayList<String> words = new ArrayList<String>();ArrayList<Integer> nums = new ArrayList<Integer>();

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);

09

Page 13: Generics CompSci 230 S2 2015 Software Construction

13

for-each loop The for-each loop is used to access each

successive value in a collection of values. Syntax:

Example:ArrayList<String> words = new ArrayList<String>();...for (String str : words) { System.out.println(str); }

for (Base_Type var :Collection_Object) Statement;

09

Page 14: Generics CompSci 230 S2 2015 Software Construction

14

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)

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());}

COMPILE-TIME ERROR

Example: TestGenericsApp

09

Page 15: Generics CompSci 230 S2 2015 Software Construction

15

Generics Vs No Generics

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]; }}

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]; }}

‘Generic type’

‘Non-generic type’

ArrayList<Item> items = new ArrayList<Item>();

‘Type argument’

‘Parameterised type’

‘Type parameter’

/‘Type variable’

09

Page 16: Generics CompSci 230 S2 2015 Software Construction

16

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 interface Comparable { public int compareTo(Object obj);}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

public class Person implements Comparable<Person> protected String irdNumber; ... public int compareTo(Person p) { return irdNumber.compareTo(p.getIRD()); }}

with Generics

09

Page 17: Generics CompSci 230 S2 2015 Software Construction

17

Generics & Subtyping Is a List of String a List of Object? Is a List of Movie a List of Item?

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!!!

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;

COMPILE-TIME ERROR

COMPILE-TIME ERROR

genericsItems.add(new Item("Sample"));Movie m1 = lm.get(0);

ERROR

09

Page 18: Generics CompSci 230 S2 2015 Software Construction

18

Generics & Subtyping So

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>

But 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

Page 19: Generics CompSci 230 S2 2015 Software Construction

19

Type wildcards Here’s a simple (no generics) method to print out

any list (without generics):

The above still works in Java 1.5, but now it generates warning messages

Next, here is an attempt using Generics

But it only takes a list of Object, but it is not a supertype of all kinds of lists.

public static void printCollection(List c) { for (Iterator i = c.iterator(); i.hasNext(); ) { System.out.println(i.next()); }}

public static void printCollection(List<Object> c) { for (Iterator<Object> i = c.iterator(); i.hasNext(); ) { System.out.println(i.next()); }}

uses unchecked or unsafe operations.

Note: Recompile with -Xlint:unchecked for

details.

List mylist = new ArrayList();…printCollection(mylist);

List<Item> mylist = new ArrayList<Item>(); printCollection(mylist); //ERROR 09

Page 20: Generics CompSci 230 S2 2015 Software Construction

20

Type wildcards <?> You should eliminate all errors and warnings in

your final code, so you need to tell Java that any type is acceptable:

<?> (i.e. any type) signifies an unbounded wildcard. (pronounced “list of unknown”)

a list whose element type matches anything = called wildcard type

public static void printCollection(List<?> c) { for (Iterator<?> i = c.iterator(); i.hasNext(); ) { System.out.println(i.next()); }}

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);

09

Page 21: Generics CompSci 230 S2 2015 Software Construction

21

for-each statement for(type var : array) {...}

or for(type var : collection) {...}

Example:

public static void printCollection(List<?> c) { for (Object e: c) { System.out.println(e); }}

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);

09

Page 22: Generics CompSci 230 S2 2015 Software Construction

22

Subtyping in generics Consider the following method:

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>)

Item

Movie

public static void printItemCollection(List<Item> il) { for (Item i: il) { System.out.println(i.getTitle()); } }

public static void printItemCollection(List<? extends Item> il) { for (Item i: il) { System.out.println(i.getTitle()); } }

09

Page 23: Generics CompSci 230 S2 2015 Software Construction

23

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

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.

public static void printItemCollection(List<? extends Item> il) { il.add(new Movie("Psycho",1960)); }

COMPILE-TIME ERROR

09