java interfaces, lists and generics essentials

27
Java Interfaces, Lists and Generics essentials SOFTENG 251 Object Oriented Software Construction

Upload: todd-coffey

Post on 02-Jan-2016

60 views

Category:

Documents


0 download

DESCRIPTION

Java Interfaces, Lists and Generics essentials. SOFTENG 251 Object Oriented Software Construction. Announcements. Make sure you filled in last Friday’s session reports Assignment 2 (due 24 th April) Demonstrate your work & understanding in lab - PowerPoint PPT Presentation

TRANSCRIPT

Java Interfaces, Lists and Generics essentials

SOFTENG 251

Object Oriented Software Construction

SOFTENG 251 Object Oriented Software Construction 2Generics in Java

Announcements

Make sure you filled in last Friday’s session reports

Assignment 2 (due 24th April) Demonstrate your work & understanding in lab

Code correctness – either in lab or through dropbox

Some updates to Wiki Additional resource link: Java Developers Almanac

http://www.exampledepot.com/ - check it out!

Exercise Bank – offline programming exercises;Utilise tutorial to go over any of these + assignment

Lecture debriefing – anything I missed out during a particular lecture/Friday session, or you didn’t get a chance to ask

Also Dols008’s lecture clarifications for Richard’s lectures

SOFTENG 251 Object Oriented Software Construction 3Generics in Java

Java Interfaces

Interfaces are special “classes” with only abstract methods i.e. über-abstract classes if you will

One major distinction: a class can “extend” (implement) multiple interfaces

So what good is a “class” with no real methods? Interfaces are useful for defining a “signature”, or a “contract”

of its implementing classes

i.e. the methods in the interface define what the implementing class should do, i.e. expected to do

Also a “cheap” way of supporting multiple inheritance

SOFTENG 251 Object Oriented Software Construction 4Generics in Java

Flyer interface All birds can fly – so can some mammals

But you can’t extend from both mammals and bird introduce a Flyer interface

Flyer<<interface>>

+fly()

public interface Flyer { public void fly();}

public class FlyingSquirrel extends Mammalimplements Flyer { public void fly() { System.out.println("Wheeee!!"); } //etc...}

public class Bird extends Animalimplements Flyer { public void fly() { System.out.println("Don’t look down"); } //etc...}

Bird

+fly()+getAge()

-age

FlyingSquirrel

+fly()+makeSound()

#name

Mammal

Flyer[] flyers = new Flyers[2];flyers[0] = new FlyingSquirrel("Yippee");flyers[1] = new Bird();for (Flyer flyer : flyers) { flyer.fly(); }

SOFTENG 251 Object Oriented Software Construction 5Generics in Java

More Interface facts

In a Java interface, you: can only define public abstract methods

(if it’s not explicitly declared public or abstract, compiler automatically makes it so)

can’t define instance variables

can only define public, static and/or final variables

Rules of inheritance and polymorphism apply to interfaces just as they do to normal classes e.g. an interface can inherit from another interface!

public interface FastFlyer extends Flyer { public void hyperdrive();}

Class implementing FastFlyer must implement both fly() and hyperdrive()

SOFTENG 251 Object Oriented Software Construction 6Generics in Java

Interface java.util.List Java’s version of the list

data structure (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

Up to actual implementers to fulfil the contract – in whatever way ArrayList, Vector (retrofitted)

LinkedList

ShoppingList

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}

SOFTENG 251 Object Oriented Software Construction 7Generics in Java

List operations & contracts

add(x)true

remove(c)true

get(3)d

indexOf(c)

2

contains(b)

true

add(3,x)true

remove(1) b

a b c d x0 1 2 3 4

a b c x0 1 2 3

d4

a b c d0 1 2

a b c d0 1 2

a b c d0 1 2 3

remove(x)false

a b c d0 1 2 3

a b c d0 1 2 3

?contains(x)false

size() 4 a b c d

0 1 2 3

4

indexOf(x)-1

c3

c4

SOFTENG 251 Object Oriented Software Construction 8Generics in Java

ArrayList & LinkedList

public class ArrayListimplements List { private Object[] elementData; private int size; ... //etc public boolean add(Object o) { elementData[size++] = o; return true; } public Object get(int i) { return elementData[i]; } public int size() { return size; } ... //etc}

a b c d0 1 2 3

e4

a b c d0 1 2 3

e4

…5 6

public class LinkedListimplements List { private Entry header; private int size; ... //etc public boolean add(Object o) { addBefore(o,header); return true; } public Object get(int i) { return entry(i).element; } public int size() { return size; } ... //etc}

SOFTENG 251 Object Oriented Software Construction 9Generics in Java

List and its implementations ArrayList and LinkedList override

each of the abstract methods in List

In overriding each method, both implementations satisfy the same contract but through very different means. E.g.

+add(Object):boolean+remove(Object):boolean+get(int):Object+indexOf(Object):int+contains(Object):boolean+size():int+iterator():Iteratoretc…

List<<interface>>

+add(Object):boolean+remove(Object):boolean+get(int):Object+indexOf(Object):int+contains(Object):bool+size():int+iterator():Iteratoretc…

-instance variables…

ArrayList

+add(Object):boolean+remove(Object):boolean+get(int):Object+indexOf(Object):int+contains(Object):bool+size():int+iterator():Iteratoretc…

-instance variables…

LinkedList

ArrayList’s remove(x):

shift all elements from indexOf(x) + 1 to the left; size--

LinkedList’s remove(x):

relink x’s previous node with x’s next node; size--

Both cases: list now is a concatenation of all elements before x and all elements after x.

SOFTENG 251 Object Oriented Software Construction 10Generics in Java

Programming scenario

Say we are writing a (very) simple personal “library” manager

Organise a collection of items – books, movies, CD’s, etc.

List items, sort items, add/remove items to library, etc

We need some kind of collection to store these items Let’s use a List ArrayList to be precise

Item

Book Movie CD

MyLibrary List Priced<<interface>>

Shirt

SOFTENG 251 Object Oriented Software Construction 11Generics in Java

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 getAuthor() { return author; } public String toString() { return "Book: '" + title + “' by " + author; }}

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

public class CD extends Item implements Priced { ... public String getPrice() {...}}

public interface Priced { public double getPrice();}

SOFTENG 251 Object Oriented Software Construction 12Generics in Java

A list of Items

Thanks to polymorphism:

Variable item of type List can point to a value of type ArrayList

We can pass in a Movie or Book as argument to add() as it accepts an Object

However because get() returns an Object, we need to downcast the result to the appropriate subtype

Book book = new Book("LOTR","Tolkien");Movie movie = new Movie("Psycho",1960);CD cd = new CD("Ozomatli",2.50);List items = new ArrayList();items.add(book); //element #0items.add(movie); //element #1items.add(cd); //element #2

Book b = (Book)items.get(0); Item bookAsItem = (Item)items.get(0);Movie m = (Movie)items.get(1);Priced forSale = (Priced)items.get(2);

public interface List { public boolean add(Object o); public Object get(int i); public int size(); //etc...}

SOFTENG 251 Object Oriented Software Construction 13Generics in Java

List of Item’s

We want items to only have objects of type Item (or its subclasses)

What happens if it doesn't?

public static void main(String[] args) { List items = new ArrayList(); populate(items); list(items);}

public static void populate(List items) { items.add(new Movie("Psycho",1960)); items.add(new Book("LOTR","Toklien"));}

public static void list(List items) { for (int i = 0; i < items.size(); i++) { Item item = (Item)items.get(i); System.out.println(i+": "+item.getTitle()); }}

SOFTENG 251 Object Oriented Software Construction 14Generics in Java

Type safety

public static void main(String[] args) { List items = new ArrayList(); populate(items); list(items);}

public static void populate(List items) { items.add(new Movie("Psycho",1960)); items.add("Terminator"); //String!}

public static void list(List items) { for (int i = 0; i < items.size(); i++) { Item item = (Item)items.get(i); System.out.println(i+": "+item.getTitle()); }}

What exactly would happen?

(Will this compile?)

SOFTENG 251 Object Oriented Software Construction 15Generics in Java

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

SOFTENG 251 Object Oriented Software Construction 16Generics in Java

What can we do instead?

Create a specialised List for Item?

public class ItemList { private List items; public boolean add(Item o) { items.add(o); } ... public Item get(int i) { return (Item) items.get(i); }} public class StringList {

private List items; public boolean add(String s) { items.add(s); } ... public String get(int i) { return (String)items.get(i); }}

Repetitive

Inefficient

Hardly scalable

public class IntList { private List items; public boolean add(Integer i) { items.add(i); } ... public Integer get(int i) { return (Integer)items.get(i); }}

SOFTENG 251 Object Oriented Software Construction 17Generics in Java

Answer: Generics!

List<Item> items = new ArrayList<Item>();...items.add(new Movie("Psycho",1960));...for (int i = 0; i < items.size(); i++) { Item item = items.get(i); ...

public class List<E> { public boolean add(E o); public E get(int i); public int size();}

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 Item (or its subclasses)

No casting necessary

Translation: List is a generic type, and it has one type parameter, which we call E

SOFTENG 251 Object Oriented Software Construction 18Generics in Java

Generic ArrayList Basically, all occurrences of

Object are “replaced” by the type variable E

Think of E as a placeholder for any possible type – just as a variable is a place-holder for any possible value

Type variables can have any name – we just chose E because it’s nice and short

Type variables themselves can be used to parameterise other generic types! (i.e. List<E>)

public class ArrayList<E> implements List<E> { private E[] elementData; private int size; ... //stuff public boolean add(E o) { elementData[size++] = o; return true; } public E get(int i) { return elementData[i]; } public int size() { return size; }}

public class List<E> { public boolean add(E o); public E get(int i); public int size();}

SOFTENG 251 Object Oriented Software Construction 19Generics in Java

Generics and type safety

public static void main(String[] args) { List<Item> items = new ArrayList<Item>(); populate(items); list(items);}

static void populate(List<Item> items) { items.add(new Movie("Psycho",1960)); items.add("Terminator");}

static void list(List<Item> items) { for (int i = 0; i < items.size(); i++) { Item item = items.get(i); System.out.println(i+": "+item.getTitle()); String wtf = (String)items.get(i); }}

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

SOFTENG 251 Object Oriented Software Construction 20Generics in Java

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

Review of lingo

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’

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

‘Type argument’

‘Parameterised type’

‘Type parameter’/‘Type variable’

SOFTENG 251 Object Oriented Software Construction 21Generics in Java

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

Type variables/parameters

new ArrayList<Item>() print("Hello");

private void print(String str) { ... int ln = str.length(); ... ... System.out.println(str);}

value of type parameter E becomes Item

value of variable str becomes "Hello"

Provide Item as type argument

Provide "Hello" as argument

SOFTENG 251 Object Oriented Software Construction 22Generics in Java

Generic methods Define generic methods just as you define generic classes Example: reverse the elements from a given vector

E.g. [a,b,c,d,e] [e,d,c,b,a]

public<T> List<T> reverse(List<T> list) { List<T> rev = new ArrayList<T>(); for (int i = list.size() - 1; i >= 0; i --) { T item = list.get(i); rev.add(item); } return rev;}

List<Movie> movies = new ArrayList<Movie>();List<String> words = new ArrayList<String>();populate(movies); populate(words);List<Movie> seivom = reverse(movies);List<String> sdrow = this.<String>reverse(words);

Note the “proper” way of calling a generic method is to parameterise it like this. However usually the compiler can infer the type in question, allowing us to omit this construct.

SOFTENG 251 Object Oriented Software Construction 23Generics in Java

(Non-generic alternative)

public List reverse(List list) { List rev = new ArrayList(); for (int i = list.size() - 1; i >= 0; i --) { Object item = list.get(i); rev.add(item); } return rev;}

List movies = new ArrayList();List words = new ArrayList();populate(movies); populate(words);List seivom = reverse(movies);List sdrow = reverse(words);

Looks simpler! But realise obviously you won’t be able to retain type

information using this method

SOFTENG 251 Object Oriented Software Construction 24Generics in Java

public<T extends Item> List<T> startsWithA(List<T> list) { List<T> filtered = new ArrayList<T>(); for (int i = 0; i < list.size(); i ++) { T item = list.get(i); if (item.getTitle().startsWith(“A”)) { filtered.add(item); } } return filtered;}

Generic methods Bounded type parameters (e.g. <T extends Item>) allow

restriction on type arguments Below: [Art,Bam,Apples,Crab,argh,Ache] [Art,Apples,Ache]

List<Movie> movies = new ArrayList<Movie>();List<String> words = new ArrayList<String>();populate(movies); populate(words);List<Movie> moviesA = startsWithA(movies);List<String> wordsA = startsWithA(words);

Notice how we can call getTitle() on item, because we know from the type parameter T’s declaration that it extends Item

SOFTENG 251 Object Oriented Software Construction 25Generics in Java

(Aside) Multiple type bounds

Can use ‘&’ operator to define multiple type bounds

public<T extends Item & Priced> void pricedItems(List<T> list) { for (int i = 0; i < list.size(); i ++) { T item = list.get(i); System.out.print("Loaning " + item.getTitle()); System.out.println(" at price " + item.getPrice()); }}

public interface Priced { public double getPrice();}

public class CD extends Item implements Priced { ...

Notice how item (of type T) can now access all methods belonging to Item and Priced

List<Movie> movies = new ArrayList<Movie>();List<CD> cds = new ArrayList<CD>();...pricedItems(movies);pricedItems(cds); Movie is a subclass of Item, but not

Priced

SOFTENG 251 Object Oriented Software Construction 26Generics in Java

Try it yourself

Revise lecture code examples

Exercises in Wiki Writing a generic Pair<E1,E2>

Writing a Chain<E> data structure

A simple differencing tool

Useful examples in the Java Almanac (see link from Wiki)

SOFTENG 251 Object Oriented Software Construction 27Generics in Java

Tutorial idea

Hands-on Generics: understanding what is/isn't possible with Generics.

Observing compiler outputs. Focus on using generic types. List and HashMap good examples.

The basics: compiler warnings with non-generic types, (good) compiler errors resulting from enforced generic types.

Sub-typing: showing sub-typing of parameterised types acts differently from sub-typing of normal types

Bounded and unbounded wildcards: how sub-typing can be done using these mechanisms