generics compsci 230 s2 2015 software construction

Post on 05-Jan-2016

220 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Generics

CompSci 230 S2 2015Software Construction

2

Agenda & Reading Topics:

Introduction Fundamentals of generic types Generics & Subtyping Type wildcards

Reading The Java Tutorial:

Generics

09

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

top related