33
1 Programming with Java Generics Angelika Langer Training/Consulting www.AngelikaLanger.com © Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved. http://www.AngelikaLanger.com/ last update: 11/6/2005 ,12:53 2 agenda ! generics overview ! refactoring legacy into generics ! building a generic abstraction

Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

1

Programming withJava Generics

Angelika LangerTraining/Consulting

www.AngelikaLanger.com

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:532

agenda

! generics overview

! refactoring legacy into generics

! building a generic abstraction

Page 2: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

2

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:533

use of non-generic collections! no homogeneous collections

"lots of casts required! no compile-time checks

"late error detection at runtime

LinkedList list = new LinkedList();list.add(new Integer(0));Integer i = (Integer)(Integer)(Integer)(Integer) list.get(0);String s = (String) (String) (String) (String) list.get(0);

casts required

fine at compile-time, but fails at runtime

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:534

use of generic collections! collections are homogeneous

"no casts necessary! early compile-time checks

"based on static type information

LinkedList<Integer><Integer><Integer><Integer> list = new LinkedList<Integer><Integer><Integer><Integer>();list.add(new Integer(0));Integer i = list.get(0);String s = list.get(0);

compile-time error

Page 3: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

3

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:535

definition of generic types

! type variable = "placeholder" for an unknown type" similar to a type, but not really a type" several restrictions

! not allowed in new expressions, cannot be derived from, no class literal, ...

interface Collection<A><A><A><A> {public void add (AAAA x);public Iterator<A><A><A><A> iterator ();

}

class LinkedList<A><A><A><A> implements Collection<A><A><A><A> {protected class Node {

AAAA elt;Node next = null;Node (A A A A elt) { this.elt = elt; }

}...

}

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:536

type parameter bounds

public class TreeMap<K K K K extends Comparableextends Comparableextends Comparableextends Comparable<K><K><K><K>,V> {private static class Entry<K,V> { ... }…private Entry<K,V> getEntry(K key) {

…while (p != null) {

int cmp = k.k.k.k.compareTocompareTocompareTocompareTo(p.(p.(p.(p.keykeykeykey))));…}…}…}

public interface Comparable<T> { public int compareTo(T arg); }

! bounds = supertype of a type variable " purpose: make available non-static methods of a type

variable" limitations: gives no access to constructors or static

methods

Page 4: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

4

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:537

using generic types! can use generic types with or without type argument

specification

" with concrete type arguments! concrete instantiation

" without type arguments! raw type

" with wildcard arguments! wildcard instantiation

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:538

concrete instantiation ! type argument is a concrete type

! more expressive type information" enables compile-time type checks

void printDirectoryNames(Collection<File><File><File><File> files) { for (File f : files)

if (f.isDirectory()) System.out.println(f);

}

List<File><File><File><File> targetDir = new LinkedList<File>();... fill list with File objects ...printDirectoryNames(targetDir);

Page 5: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

5

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:539

! no type argument specified

! permitted for compatibility reasons" permits mix of non-generic (legacy) code with generic

code

raw type

void printDirectoryNames(CollectionCollectionCollectionCollection files) { for (Iterator it = files.iterator(); it.hasNext(); ) {

File f = (File)(File)(File)(File) it.next();if (f.isDirectory()) System.out.println(f);

}}

List<File><File><File><File> targetDir = new LinkedList<File>();... fill list with File objects ...printDirectoryNames(targetDir);

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5310

wildcard instantiation! type argument is a wildcard

! a wildcard stands for a family of types" bounded and unbounded wildcards supported

void printElements(Collection<?><?><?><?> c) { for (Object e : c)

System.out.println(e);}

CollectionCollectionCollectionCollection<File><File><File><File> targetDir = new LinkedList<File>();... fill list with File objects ...printElements(targetDir);

Page 6: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

6

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5311

generic methods & type inference! defining a generic methodclass Utilities {public static <A <A <A <A extends Comparableextends Comparableextends Comparableextends Comparable<A>><A>><A>><A>> A max(Iterable<A> c) {

A result;for (A a : c) { if (result.compareTo(a) <0) result = a; }return result;

}}

! invoking a generic method" no special invocation syntax

! type arguments are inferred from actual arguments (type inference)

public static void main (String[ ] args) {LinkedList<Byte> byteList = new LinkedList<Byte>();...Byte y = UtilitiesUtilitiesUtilitiesUtilities....maxmaxmaxmax(byteList);}

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5312

agenda

! generics overview

! refactoring legacy into generics

! building a generic abstractions

Page 7: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

7

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5313

transition to generic Java! refactoring legacy from non-generic to generic

Java has two aspects

1. refactoring code that uses generified types totake advantage of generification

2. generification of non-generic types and methods

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5314

agenda

! generics overview

! refactoring legacy into generics"usage of generified types and methods

"generification of types and methods

! building a generic abstractions

Page 8: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

8

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5315

refactoring usage code

! refactoring code that uses generified types is relatively easy" IDEs have refactoring support

! example: JDK collection framework" List has been generified to List<E>" code that uses List must now say: "list of

what"

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5316

usage of generified types! before refactoring

! start providing type arguments" Collection => Collection<String> oder Collection<File>

" leads to warning when iterator() method is called

public static CollectionCollectionCollectionCollectionremoveDirectory(CollectionCollectionCollectionCollection absoluteFiles,

String directoryToBeRemovedFromPath) {CollectionCollectionCollectionCollection relativeFileNames = new HashSetHashSetHashSetHashSet();IteratorIteratorIteratorIterator iter = absoluteFiles.iterator();while (iter.hasNext()) {

relativeFileNames.add(FileUtility.relativePath(((File)iter.next()).getPath(),directoryToBeRemovedFromPath));

}return relativeFileNames;

}

Page 9: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

9

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5317

usage of generified types

! challenge: elimination of no longer needed casts"spread over the entire program"no indication in form of a warning

public static Collection<String><String><String><String>removeDirectory(Collection<File><File><File><File> absoluteFiles,

String directoryToBeRemovedFromPath) {Collection<String><String><String><String> relativeFileNames = new HashSet<String><String><String><String>();Iterator<File><File><File><File> iter = absoluteFiles.iterator();while (iter.hasNext()) {

relativeFileNames.add(FileUtility.relativePath(((File)(File)(File)(File)iter.next()).getPath(),directoryToBeRemovedFromPath));

}return relativeFileNames;

}

can be eliminated

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5318

agenda

! generics overview

! refactoring legacy into generics"usage of generified types and methods

"generification of types and methods

! building a generic abstractions

Page 10: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

10

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5319

generifying legacy code! refactor non-generic abstraction

"turn it into a generic abstraction"provided it is intrisically generic

! example: JDK collections"re-engineer Collection into generic Collection<E>"retain semantics of Collection interface"new generic interface must be compatible with old

non-generic interface

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5320

step 1! methods that take or return a single element

" replace Object by type parameter

interface Collection {boolean add (ObjectObjectObjectObject o);boolean contains(ObjectObjectObjectObject o);boolean remove (ObjectObjectObjectObject o);...

}

before:

interface Collection<E><E><E><E> {boolean add (EEEE o);boolean contains(EEEE o);boolean remove (EEEE o);...

}

after:

Page 11: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

11

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5321

have the semantics been preserved?before: mixed-type collections are the norm

after: mixed-type operations do not compile

Collection c = new HashSet();c.add(new StringStringStringString("abc"));c.add(new DateDateDateDate());boolean b = c.contains(LongLongLongLong(0));

Collection<Date><Date><Date><Date> c = new HashSet<Date>();c.add(new StringStringStringString("abc"));c.add(new DateDateDateDate());boolean b = c.contains(LongLongLongLong(0));

error

error

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5322

semantics (cont.)

! consequence:"a mixed-type collection must be declared as

such"e.g. as Collection<Object>

Collection<ObjectObjectObjectObject> c = new HashSet<ObjectObjectObjectObject>();c.add(new String("abc"));c.add(new Date());boolean b = c.contains(Long(0));

Page 12: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

12

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5323

JDK Collection! actual generification in the JDK is different

interface Collection<E> {boolean add (E o);boolean contains(ObjectObjectObjectObject o);boolean remove (ObjectObjectObjectObject o);...

}

JDK:

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5324

discussion

! JDK generification is more relaxed"contains(ObjectObjectObjectObject) allows passing arguments

through any type of reference, not just through references to type E

Collection<LongLongLongLong> c = ...

void f(ObjectObjectObjectObject ref) {...c.contains(ref);

c.contains((Long)ref);...

}

JDK permits:

we require:

Page 13: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

13

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5325

step 2! methods that take a collection

" replace Collection by Collection<E>

interface Collection {boolean addAll (CollectionCollectionCollectionCollection o);boolean containsAll(CollectionCollectionCollectionCollection o);boolean removeAll (CollectionCollectionCollectionCollection o);boolean retainsAll (CollectionCollectionCollectionCollection o);...}

before:

interface Collection<E><E><E><E> {boolean addAll (Collection<E>Collection<E>Collection<E>Collection<E> o);boolean containsAll(Collection<E>Collection<E>Collection<E>Collection<E> o);boolean removeAll (Collection<E>Collection<E>Collection<E>Collection<E> o);boolean retainsAll (Collection<E>Collection<E>Collection<E>Collection<E> o);...}

after:

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5326

have the semantics been preserved?before: could use any type of collection

after: collection of different element type not permitted

ListListListList l = ...SetSetSetSet s = ...CollectionCollectionCollectionCollection c = ...c.removeAll(l);c.containsAll(s);

List<Long>List<Long>List<Long>List<Long> l = ...Set<Set<Set<Set<ObjectObjectObjectObject>>>> s = ...CollectionCollectionCollectionCollection<<<<NumberNumberNumberNumber>>>> c = ...c.removeAll(l);c.containsAll(s);

error

error

Page 14: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

14

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5327

alternative! allow all types of collections

" replace Collection by Collection<?>

interface Collection<E> {boolean addAll (Collection<?> o);boolean containsAll(Collection<?> o);boolean removeAll (Collection<?> o);boolean retainsAll (Collection<?> o);...}

2nd try:

List<Long>List<Long>List<Long>List<Long> l = ...Set<Set<Set<Set<ObjectObjectObjectObject>>>> s = ...CollectionCollectionCollectionCollection<<<<NumberNumberNumberNumber>>>> c = ...c.removeAll(l);c.containsAll(s); c.addAll(s); does it make sense?

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5328

discussionQ: Do we want to allow addition, removal, search of

arbitrary objects to a collection of number?A: Certainly not - but who prohibits it?

two choices:" method accepts all types of elements and checks for

itself (dynamically at runtime)" method signature excludes arbitrary types of elements

and the compiler checks (at compile-time)

Page 15: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

15

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5329

alternative! allow collections with same element type or

subtype thereof" replace Collection by Collection<? extends E>

interface Collection<E> <E> <E> <E> {boolean addAll (Collection<? extends E><? extends E><? extends E><? extends E> o);boolean containsAll(Collection<? extends E> <? extends E> <? extends E> <? extends E> o);boolean removeAll (Collection<? extends E><? extends E><? extends E><? extends E> o);boolean retainsAll (Collection<? extends E><? extends E><? extends E><? extends E> o);...

}

3rd try:

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5330

alternative! in a collection of numbers we can add, remove

search for longs, but not for arbitrary objects

List<Long>List<Long>List<Long>List<Long> l = ...Set<Set<Set<Set<ObjectObjectObjectObject>>>> s = ...CollectionCollectionCollectionCollection<<<<NumberNumberNumberNumber>>>> c = ...

c.removeAll(l);

c.containsAll(s);

c.addAll(s);

c.addAll(l);

error

error

Page 16: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

16

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5331

alternative without wildcards! parameterize the methods

" has the advantage of no restrictions on use of argument

" wildcard type restricts usage

interface Collection<E><E><E><E> {<F extends E><F extends E><F extends E><F extends E> boolean addAll (Collection<F> o);<F extends E><F extends E><F extends E><F extends E> boolean containsAll(Collection<F> o);<F extends E><F extends E><F extends E><F extends E> boolean removeAll (Collection<F> o);<F extends E><F extends E><F extends E><F extends E> boolean retainsAll (Collection<F> o);...

}

4th try:

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5332

JDK Collection! actual generification in the JDK is different

interface Collection<E> {boolean addAll (Collection<? extends E> o);boolean containsAll(Collection<?><?><?><?> o);boolean removeAll (Collection<?><?><?><?> o);boolean retainsAll (Collection<?><?><?><?> o);...

}

JDK:

Page 17: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

17

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5340

step 4! methods that convert collection to array

" replace Object by type parameter

interface Collection {Object[] toArray();Object[] toArray(Object[] a);...

}

before:

interface Collection<E><E><E><E> {EEEE[] toArray();EEEE[] toArray(EEEE[] a);...

}

after:

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5341

problem

! E[] toArray() is clearly wrong"collections is incapable of returning an array of E"arrays of type variables are not allowed

class Sequence<E> implements Collection<E> {...EEEE[][][][] toArray() {

E[] arr = new Enew Enew Enew E[size];

... fill array with collection elements ...}...

}

does not compile

Page 18: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

18

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5342

problem (cont.)! if new E[] were allowed ...

"what would it look like after type erasure ?

! solution:" retain the original signature and return Object[]

class Sequence implements Collection {...ObjectObjectObjectObject[] [] [] [] toArray() {

Object[] arr = new Objectnew Objectnew Objectnew Object[size];

... fill array with collection elements ...}...

}

E replacedby Object

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5343

problem! E[] toArray(E[]) is too restrictive

" return type need not be "array of element type"" original semantics:

! argument type (of array supplied) determines runtime type of result

! problem:" cannot put elements into array of supertype

! although it was possible in non-generic Collection

Collection<Long><Long><Long><Long> longs = ...;

NumberNumberNumberNumber[][][][] numbers = longs.toArray(new Numbernew Numbernew Numbernew Number[0]); error

Page 19: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

19

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5344

solution! solution:

" generify the method

! note" implementation uses reflection to create array of

correct type

interface Collection<E><E><E><E> {...<T> T<T> T<T> T<T> T[][][][] toArray(TTTT[][][][] a);...

}

2nd try:

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5345

JDK Collection! actual generification in the JDK is the same

interface Collection<E> {ObjectObjectObjectObject[] toArray();<T> T<T> T<T> T<T> T[] toArray(TTTT[][][][] a);...

}

JDK:

Page 20: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

20

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5346

conclusion! refactoring a non-generic abstraction into a

generic one is non-trivial" because original semantics must be retained and" generic API must not be more restrictive that the

original

! not discussed here:" byte code compatibility is also required" usually happens automatically" sometimes "interesting" hacks are necessary

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5347

Collections.max()! method that finds maximum element in collection

of comparable elements" use bound to make sure elements are comparable" use wildcards to permit supertype of element type as

return type

class Collections {static Object max(Collection coll) {...}...}

before:

class Collections {static <T extends Comparable<? super T>><T extends Comparable<? super T>><T extends Comparable<? super T>><T extends Comparable<? super T>>TTTT max(Collection<T><T><T><T> coll) {...}...}

after:

Page 21: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

21

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5348

JDK Collection! actual generification in the JDK is different

class Collections {static <T extends ObjectObjectObjectObject & Comparable<? super T>>T max(Collection<? extends T> coll) {...}...

}

JDK:

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5349

problem! our API is not backward compatible

" by using bounded type parameter we change return type

class Collections {static ObjectObjectObjectObject max(Collection coll) {...}...}

before:

class Collections {static <T extends <T extends <T extends <T extends ComparableComparableComparableComparable<? super T>><? super T>><? super T>><? super T>>

TTTT max(Collection<T> coll) {...}...}

after:

class Collections {static ComparableComparableComparableComparable max(Collection coll) {...}...}

type erased:

Page 22: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

22

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5350

agenda

! generics overview

! refactoring legacy into generics

! building a generic abstractions

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5351

a generic Pair class! Implement a class that holds two elements of

different types.

"Constructors"Getters and Setter"Equality and Hashing"Comparability"Cloning"Value Semantics

final class Pair<X,Y> {private X first;private Y second;...

}

Page 23: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

23

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5352

constructors - 1st naive approachfinal class Pair<X,Y> {

...public Pair(X x, Y y) {

first = x; second = y;}public Pair() {

first = null; second = null;}public Pair(PairPairPairPair other) {

if (other == null) {first = null; second = null;

} else {first = other.first; first = other.first; first = other.first; first = other.first; second = other.second;second = other.second;second = other.second;second = other.second;

}}

}

error: incompatible types

ObjectObjectObjectObjectYYYY

! does not compile

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5353

constructors - tentative fixfinal class Pair<X,Y> {

...public Pair(X x, Y y) {

first = x; second = y;}public Pair() {

first = null; second = null;}public Pair(Pair other) {

if (other == null) {first = null; second = null;

} else {first = (X)(X)(X)(X)other.first; second = (Y)(Y)(Y)(Y)other.second;

}}

}

warning: unchecked cast

YYYYYYYY

! insert cast

Page 24: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

24

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5354

ignoring unchecked warnings! what happens if we ignore the warnings?

! error detection at runtime long after debatable assigment in constructor

public static void main(String... args) {Pair<String,IntegerString,IntegerString,IntegerString,Integer> p1

= new Pair<String,Integer>("Bobby",10);Pair<String,DateString,DateString,DateString,Date> p2

= new Pair<String,Date>(p1);...Date bobbysBirthday = p2.getSecond();

}

ClassCastException

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5355

constructors - what's the goal?! a constructor that takes the same type of pair?

! allow creation of one pair from another pair of a different type, but with compatible members?

Page 25: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

25

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5356

same type argumentpublic Pair(Pair<X,Y>Pair<X,Y>Pair<X,Y>Pair<X,Y> other) {

if (other == null) {first = null;second = null;

}else {

first = other.first;second = other.second;

}}

public static void main(String... args) {Pair<String,IntegerString,IntegerString,IntegerString,Integer> p1

= new Pair<String,Integer>("Bobby",10);Pair<String,DateString,DateString,DateString,Date> p2

= new Pair<String,Date>(p1);...Date bobbysBirthday = p2.getSecond();

}

error: no matching ctor

! accepts same typepair

! rejects alien pair

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5357

downside! implementation also rejects useful cases:public static void main(String... args) {Pair<String,IntegerString,IntegerString,IntegerString,Integer> p1

= new Pair<String,Integer>("planet earth",10000);Pair<String,NumberString,NumberString,NumberString,Number> p2 = new Pair<String,Number>(p1);

Long thePlanetsAge = p2.getSecond();}

error: no matching ctor

Page 26: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

26

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5358

compatible type argumentpublic <A extends X, B extends YA extends X, B extends YA extends X, B extends YA extends X, B extends Y> Pair(Pair<A,B> other) {

if (other == null) {first = null;second = null;

}else {

first = other.first;second = other.second;

}}

public static void main(String... args) {Pair<String,IntegerString,IntegerString,IntegerString,Integer> p1 = new Pair<String,Integer>("planet earth",10000);

Pair<String,NumberString,NumberString,NumberString,Number> p2 = new Pair<String,Number>(p1);

Long thePlanetsAge = p2.getSecond();}

now fine

! accepts compatible pair

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5359

what does "compatible" mean?! subtyping relationship

"all extends and implements relationships"covariance relationship between “array of

subtype” and “array of supertype”"relationship between wildcard instantiations and

concrete instantiations of parameterized types

! examples:" Pair<Object,Object[]> created from Pair<String,String[]>

" Pair<String,? extends Number>> created from Pair<String,Integer>

Page 27: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

27

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5360

equivalent implementation

! difference lies in methods that can be invoked on other" no restriction in generic method" no methods that take arguments of "unknown" type in method with

wildcard argument

! does not matter since we do not invoke any methods

public Pair(Pair<? extends X,? extends Y>Pair<? extends X,? extends Y>Pair<? extends X,? extends Y>Pair<? extends X,? extends Y> other) {if (other == null) {

first = null;second = null;

}else {

first = other.first;second = other.second;

}}

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5361

getters and setters

! add setters that take the new value from anotherpair

final class Pair<X,Y> {...public X getFirst() { return first; }public Y getSecond() { return second; }public void setFirst(X x) { first = x; }public void setSecond(Y y) { second = y; }

}

Page 28: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

28

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5368

comparison

! use bounds to require that members be comparable

final class Pair<X,Y> implements Comparable<Pair<X,Y>>implements Comparable<Pair<X,Y>>implements Comparable<Pair<X,Y>>implements Comparable<Pair<X,Y>> {…public int compareTo(Pair<X,Y> other) { ... first.compareTo(other.first) ...... second.compareTo(other.second) ...

}}

error: cannot find compareTo method

final class Pair<X extends Comparable<X>X extends Comparable<X>X extends Comparable<X>X extends Comparable<X>,Y extends Comparable<Y>Y extends Comparable<Y>Y extends Comparable<Y>Y extends Comparable<Y>>

implements Comparable<Pair<X,Y>> {…public int compareTo(Pair<X,Y> other) { ... first.compareTo(other.first) ...... second.compareTo(other.second) ...

}}

now fine

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5369

comparison! the proposed implementation does not permit pairs

of "incomparable" types" such as Pair<Number,Number>

" two flavours of generic pair class would be idealclass Pair<X,Y>class Pair<X,Y>class Pair<X,Y>class Pair<X,Y>

and class Pair<Xclass Pair<Xclass Pair<Xclass Pair<X extendsextendsextendsextends Comparable<X>,Comparable<X>,Comparable<X>,Comparable<X>,

YYYY extendsextendsextendsextends Comparable<Y>> Comparable<Y>> Comparable<Y>> Comparable<Y>>

implementsimplementsimplementsimplements Comparable<Pair<X,Y>>Comparable<Pair<X,Y>>Comparable<Pair<X,Y>>Comparable<Pair<X,Y>>

" cannot define two flavors of same generic class

Page 29: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

29

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5370

multi-class solution! define separate classesclass Pair<X,Y>Pair<X,Y>Pair<X,Y>Pair<X,Y> {

protected final int compareToImpl(Pair<? extends Comparable<X>,

? extends Comparable<Y>> other) {...

}}

class ComparablePair<X extends Comparable<X>, ComparablePair<X extends Comparable<X>, ComparablePair<X extends Comparable<X>, ComparablePair<X extends Comparable<X>, Y extends Comparable<Y>>Y extends Comparable<Y>>Y extends Comparable<Y>>Y extends Comparable<Y>>

extends Pair<X,Y> extends Pair<X,Y> extends Pair<X,Y> extends Pair<X,Y> implements Comparable<ComparablePair<X,Y>>implements Comparable<ComparablePair<X,Y>>implements Comparable<ComparablePair<X,Y>>implements Comparable<ComparablePair<X,Y>> {

public int compareTo(ComparablePair<X,Y> other) {return super.compareToImpl(other);

}}

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5371

multi-class solution - evaluation! leads to an inflation of classes

" ComparablePair, CloneablePair, ComparableCloneablePair, ...

! cannot compare compatible types" ComparablePair<Integer,Integer> cannot be

compared to ComparablePair<Number,Number>

"inconsistent with our implementation of equals()

Page 30: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

30

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5372

single-class solution! allow comparison of compatible pairs

! alternatively with raw type

final class Pair<X,Y> implements Comparable<Pair<?,?>> implements Comparable<Pair<?,?>> implements Comparable<Pair<?,?>> implements Comparable<Pair<?,?>> {…public int compareTo(Pair<?,?>Pair<?,?>Pair<?,?>Pair<?,?> other) {…

}}

final class Pair<X,Y> implements Comparable<Pair> implements Comparable<Pair> implements Comparable<Pair> implements Comparable<Pair> {…public int compareTo(PairPairPairPair other) {…

}}

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5374

"unchecked" warnings

! suppress with standard annotation

class Foo {@@@@SuppressWarningsSuppressWarningsSuppressWarningsSuppressWarnings("unchecked")("unchecked")("unchecked")("unchecked")void f() {

// code in which unchecked warnings are suppressed.}}

final class Pair<X,Y> implements Comparable<Pair<?,?>> {public int compareTo(Pair<?,?>Pair<?,?>Pair<?,?>Pair<?,?> other) {

... ((Comparable)(Comparable)(Comparable)(Comparable)first).compareTo(other.first) ...}

}

warning: unchecked cast

Page 31: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

31

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5375

clone

! two choices"two separate classes Pair and CloneablePair"one unified class Pair

class CloneablePair<X extends Cloneable, Y extends Cloneable> extends Pair<X,Y>

implements Cloneable {…

public CloneablePair<X,Y> clone() {…

}}

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5376

single-class solution

! again: unavoidable „unchecked“ warnings"because clone() returns an Object

class Pair<X,Y> implements Comparable<Pair<?,?>>, Cloneable {public Pair<X,Y> clone()

throws CloneNotSupportedException {... (X)(X)(X)(X)first.getClass().getMethod("clone",null)

.invoke(first,null); ...}

}warning: unchecked cast

Page 32: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

32

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5381

closing remarks! greatest difficulty is clash between old and new

Java" where generic Java meets non-generic Java

! rules of thumb:1. avoid raw types whenever you can2. avoid casts to parameterized types whenever

you can

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5382

wrap-up

! refactoring legacy code to generic code"adds to the clarity of the code"is easy for code that uses generified

abstractions"generifying an existing abstraction takes care"designing generic APIs is non-trivial

Page 33: Programming with Java Generics - Angelika Langer€¦ · Java Generics Angelika Langer Training/Consulting ... Java has two aspects 1. refactoring code that uses generified types

33

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5383

referencesGenerics in the Java Programming Language

a tutorial by Gilad Bracha, July 2004http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf

Java Generics FAQa FAQ by Angelika Langerhttp://www.AngelikaLanger.com/GenericsFAQ/JavaGenericsFAQ.html

more links ...http://www.AngelikaLanger.com/Resources/Links/JavaGenerics.htm

© Copyright 2005 by Angelika Langer & Klaus Kreft. All Rights Reserved.http://www.AngelikaLanger.com/last update: 11/6/2005 ,12:5384

authors

Angelika LangerTrainer/Consultant URL: www.AngelikaLanger.comEmail: [email protected]

Klaus KreftSenior ConsultantSiemens Business ServicesEmail: [email protected]