Java Generics: a deep dive

81
RJUG : 12-Dec-2012 Bryan Basham – Java Generics: a Deep Dive Slide 1 © Copyright 2012, Software Alchemy History & Theory Java Generics: a Deep Dive Creating a Generic Method Creating a Generic Class Recursive Generic Types Generics in Frameworks Creating a Generic Framework Odds & Sods Java Generics Bryan Basham Software Alchemy [email protected] http://www.linkedin.com/in/SoftwareAlchemist

description

If you've programmed in Java in the past decade then you know what generic types are. Generics are used everywhere but rarely understood on a deep level. In this talk, Bryan will show not only classic "container" generic classes but also how to build simple, but highly flexible frameworks in all tiers (GUI, Service and DAO tiers).

Transcript of Java Generics: a deep dive

Page 1: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 1

© Copyright 2012, Software Alchemy

History& Theory

Java Generics:a Deep Dive

Creating aGeneric Method

Creating aGeneric Class

RecursiveGeneric Types

Generics inFrameworks

Creating aGeneric

Framework

Odds & Sods

Java Generics

Bryan BashamSoftware Alchemy

[email protected]

http://www.linkedin.com/in/SoftwareAlchemist

Page 2: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 2

© Copyright 2012, Software Alchemy

Java Generics:a Deep Dive

Creating aGeneric Method

RecursiveGeneric Types

Generics inFrameworks

Creating aGeneric

Framework

Odds & Sods

Mixing w/Raw Types

ErasureHistory

Wildcards & PECS

History& Theory

Creating aGeneric Class

History & Theory

Page 3: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 3

© Copyright 2012, Software Alchemy

Why Are Generics Important?

● The great debate of dynamic vs static languages

– Dynamic is great for rapid prototyping– Static is better for serious engineering– I love both, but...

● This talk is about serious engineering, so...– Let the compiler catch more potential bugs– Apply more rigor to your designs– Add more flexibility to your designs

Page 4: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 4

© Copyright 2012, Software Alchemy

History

● Generic types were introduced in J2SE 5.0 in 2004

– Additional type safety– Reduced the need for casting

● Pre-generics code example:List v = new ArrayList();v.add(“test”);Integer i = (Integer) v.get(0); // Run-time error

● Post-generics:List<String> v = new ArrayList<String>();v.add(“test”);Integer i = v.get(0); // Compile-time error

Page 5: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 5

© Copyright 2012, Software Alchemy

Theory

● Unlike C++ templates– Primitives cannot be type parameters

List<int> numbers; // not legal

– Only one generated code file● Generics are a compile-time feature

– At run-time type variables (eg T) become Object– This is called erasure

public class LispList<T> { public class LispList { private T item; private Object item; private LispList<T> next; private LispList next; public T first() {...} public Object first() {...} // etc... // etc...} }

Page 6: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 6

© Copyright 2012, Software Alchemy

Terminology

● Generic type:public class LispList<T> { ... }

public class Pair<T1, T2> { ... }

● Parameterized type:LispList<String> list = new LispList<String>("first");

Pair<String,Integer> p1 = new Pair<String,Integer>("random number", 47);

● Type inference in Java 7:Pair<String,Integer> p1 = new Pair<>("random number", 47);

Map<FrequencyCategory, Map<RecencyCategory, EnumMap<RfmAnalysisStatistic, Number>>> rfmContent = new HashMap<>();

Type Argument(required in Java 5 & 6)

“the diamond”

Type Parameter

Page 7: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 7

© Copyright 2012, Software Alchemy

More Terminology

● Generic method:public void printPair(Pair<?,?> p) { System.out.println("(" + p.getFirst() + "," + p.getSecond() + ")");}

● Bounded wildcards:public interface DomainEntityDAO<T extends DomainEntity> { public long create(T entity); public T findById(long id);}

public static <T> void flush(Collection<T> coll, Sink<? super T> sink) { // flush all elements in the collection to the sink}

Wildcard Argument(unbounded)

Upper-Bound Wildcard

Lower-Bound WildcardGeneric Method Type Parameter

Page 8: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 8

© Copyright 2012, Software Alchemy

The PECS Principle

● Producers use extends:public T something() { /* this method produces a T or subclasses */ }

● Consumers use super:public void something(T) { /* this method consumes a T or ancestors */ }

● So what?// from the java.util.Collections API:

public static <T> T max(Collection<? extends T> collection, Comparator<? super T> comparator)

● More explanation: click here

The collection produces elementsto compare to find the max.

The comparator consumes elementswhile performing the comparison.

Page 9: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 9

© Copyright 2012, Software Alchemy

Mixing Raw Types with Generics

● A raw type is a use of a generic type without type arguments:

List<String> list1 = new ArrayList();// legal, but with warnings list1.add("abc"); list1.add(47); // not legal

– Compiler treats this as a list of strings (only); the type info is on the variable not the RT object

@SuppressWarnings("rawtypes") // use this to suppress warnings List<?> list3 = new ArrayList(); list3.add("abc"); // not legal list3.add(47); // not legal list3.add(null); // null is the only legal value

– Compiler treats this as a list of unknown values

Raw Type

Page 10: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 10

© Copyright 2012, Software Alchemy

Mixing Raw Types with Generics

● More examples: List list5 = new ArrayList<String>(); list5.add("abc"); // legal list5.add(47); // legal, but not type-safe

– Compiler treats this as a list of anything List list6 = new ArrayList<?>(); // compiler error

– Not legal to use wildcards in instantiation syntax● Don't mix raw types with generic types

– Unless integrating with legacy APIs– NEVER use raw types in new code

Page 11: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 11

© Copyright 2012, Software Alchemy

Java Generics:a Deep Dive

Creating aGeneric Method

RecursiveGeneric Types

Generics inFrameworks

Creating aGeneric

Framework

Odds & Sods

Mixing w/Raw Types

ErasureHistory

Wildcards & PECS

History& Theory

Complex Ex

Simple Ex

Multiple Type Params

Other Types

Creating aGeneric Class

Creating a Generic Class

Page 12: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 12

© Copyright 2012, Software Alchemy

A Simple Example

● A class with one type parameter:public class Optional<T> {

private final T item;

public Optional(T item) { this.item = item; }

public boolean isPresent() { return item != null; } public T or(T defaultValue) { return item != null ? item : defaultValue; } public T get() { if (item != null) { return item; } else { throw new IllegalStateException(); } }}

Page 13: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 13

© Copyright 2012, Software Alchemy

A Simple Example: Unit Tests

● A class with one type parameter: @Test public void test() { Integer item = null; Optional<Integer> opt = new Optional<Integer>(item); assertTrue(!opt.isPresent()); assertEquals(47, opt.or(47).intValue()); try { int value = opt.get(); fail(); } catch (IllegalStateException e) { /* succeeds */ }

item = 42; opt = new Optional<Integer>(item); assertTrue(opt.isPresent()); assertEquals(42, opt.or(47).intValue()); assertEquals(42, opt.get().intValue()); }

● BTW, this is a hack of a real Guava class

Page 14: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 14

© Copyright 2012, Software Alchemy

Example: Classic link list

● A LISP-like linked list implementation:public class LispList<T> { private final T head; private LispList<T> tail;

public LispList(T head) { this.head = head; }

public T first() { return head; } public LispList<T> rest() { return tail; } public LispList<T> addToFront(T item) { LispList<T> newHead = new LispList<T>(item); newHead.tail = this; return newHead; }}

Page 15: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 15

© Copyright 2012, Software Alchemy

Example: Classic link list

● Simple usage test: @Test public void testAdd() { LispList<String> list = new LispList<String>("first"); list = list.addToFront("second"); list = list.addToFront("third"); list = list.addToFront("fourth"); // test the link chain assertEquals("fourth", list.first()); // car assertEquals("third", list.rest().first()); // cadr assertEquals("second", list.rest().rest().first()); // caddr assertEquals("first", list.rest().rest().rest().first()); }

Page 16: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 16

© Copyright 2012, Software Alchemy

Example: Classic link list

● Use generic interfaces to extend behavior:public class LispList<T> implements Iterable<T> { // skip previous code @Override public Iterator<T> iterator() { return new LispListIterator<T>(this); } private static class LispListIterator<T> implements Iterator<T> { private LispList<T> currentHead; private LispListIterator(LispList<T> listHead) { currentHead = listHead; } @Override public boolean hasNext() { return currentHead != null; } @Override public T next() { T item = currentHead.head; currentHead = currentHead.tail; return item; } @Override public void remove() { throw new UnsupportedOperationException(); } }}

Page 17: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 17

© Copyright 2012, Software Alchemy

Example: Classic link list

● Test the iterable behavior: @Test public void testAdd() { LispList<Integer> list = new LispList<Integer>(0); list.addToEnd(1); list.addToEnd(2); list.addToEnd(3); // int count = 0; for (int value : list) { assertEquals(count++, value); } }

You can use any Iterable as thetarget of a for-each statement.

Page 18: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 18

© Copyright 2012, Software Alchemy

Using Multiple Type Params

● A class with two type parameters:public class Pair<T1, T2> {

private final T1 first; private final T2 second;

public Pair(T1 o1, T2 o2) { this.first = o1; this.second = o2; }

public T1 getFirst() { return first; }

public T2 getSecond() { return second; }}

Page 19: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 19

© Copyright 2012, Software Alchemy

Using Multiple Type Args

● Unit test for our Pair class: @Test public void test1() { Pair<String, Long> p1 = new Pair<String, Long>("a test", 47L); assertEquals("a test", p1.getFirst()); assertEquals(new Long(47), p1.getSecond());

// Java 7 Pair<String, Long> p2 = new Pair<>("life & everything", 42L); assertEquals("life & everything", p2.getFirst()); assertEquals(new Long(42), p2.getSecond()); }

Page 20: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 20

© Copyright 2012, Software Alchemy

Generic Interfaces

● A generic function to determine the truth of some condition:

public interface Predicate<T> { public boolean apply(T input);}private static final Predicate<Integer> IS_EVEN_P = new Predicate<>() { public boolean apply(Integer input) { return input % 2 == 0; }};

● A generic function to transform an input from one value to another:

public interface Function<FROM, TO> { public TO apply(FROM input);}

● BTW, these are also part of Guava; one of my favorite Java libraries

Page 21: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 21

© Copyright 2012, Software Alchemy

Predicate Unit Test

@Test public void predicateTest() { List<AppParameter> parameters = new ArrayList<>(); parameters.add(p1 = new AppParameter(PARAM1, VALUE1)); parameters.add(p2 = new AppParameter(PARAM2, VALUE2)); parameters.add(p3 = new AppParameter(PARAM3, VALUE3)); // change a few values p1.setValue(NEW_VALUE1); p2.setValue(NEW_VALUE2); // test the "is dirty" function Collection<AppParameter> dirtyList = CollectionUtils.gather(parameters, new Predicate<>() { @Override public boolean apply(AppParameter input) { return input.isDirty(); }; }); assertEquals(2, dirtyList.size()); }

Page 22: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 22

© Copyright 2012, Software Alchemy

Other Generic Types

● These types can be made generic...– Classes– Interfaces– Inner classes, etc

● These Java types may not be generic:– Anonymous inner classes– Exceptions– Enums

Page 23: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 23

© Copyright 2012, Software Alchemy

Java Generics:a Deep Dive

RecursiveGeneric Types

Generics inFrameworks

Creating aGeneric

Framework

Odds & Sods

Mixing w/Raw Types

ErasureHistory

Wildcards & PECS

History& Theory

Complex Ex

Simple Ex

Multiple Type Params

Other Types

Creating aGeneric Class

Complex Ex

Simple Ex

PECS Reprised

Creating aGeneric Method

Creating a Generic Method

Page 24: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 24

© Copyright 2012, Software Alchemy

Why Generic Methods?

● Generic methods allow you to create algorithms that apply to a wide variety of types.

● For example, how many sorting algorithms do you need?

– Sort a list of integers– Sort a list of dates– Sort a list of strings

● What do these all have in common?

Page 25: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 25

© Copyright 2012, Software Alchemy

A Simple Generic Method

● Gather all items in a collection that satisfy the given predicate:

public static <T> Collection<T> gather(final Iterable<T> collection, final Predicate<T> predicate) {

checkNotNull(collection, "collection must not be null"); checkNotNull(predicate, "predicate must not be null");

Collection<T> result = new ArrayList<T>(); for (T item : collection) { if (predicate.apply(item)) { result.add(item); } } return result; }

Page 26: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 26

© Copyright 2012, Software Alchemy

A gather Method Unit Test

@Test public void testGather() { // Gather negative numbers Collection<Integer> test1 = CollectionUtils.gather(Arrays.asList(TEST_NUMS), IS_NEG); assertEquals(test1.size(), NEG_NUMBERS_ARRAY.length); for (Integer n : NEG_NUMBERS_ARRAY) { assertTrue("elements are correct", test1.contains(n)); } } private static final Integer[] TEST_NUMS = { -42, 42, 0, 13, -47, 42, 42, 47 }; private static final Integer[] NEG_NUMBERS_ARRAY = { -42, -47 }; private static final Predicate<Integer> IS_NEG = new Predicate<>() { public boolean apply(Integer input) { return input < 0; } };

Does anyone see the bug in this code?

Page 27: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 27

© Copyright 2012, Software Alchemy

A More Complex Example

● A mapping operation: public static <F, T> Collection<T> map( final Collection<F> collection, final Function<F, T> transformer) {

checkNotNull(collection, "collection must not be null"); checkNotNull(transformer, "transformer must not be null");

Collection<T> result = new ArrayList<T>(); for (F item : collection) { result.add(transformer.apply(item)); } return result; }

Page 28: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 28

© Copyright 2012, Software Alchemy

A More Complex Example

@Test public void testMap() { // Square all of the test numbers Collection<Integer> test1 = CollectionUtils.map(TEST_NUMBERS, SQUARE); assertEquals(test1.size(), TEST_NUMBERS.size()); Iterator<Integer> numbers = TEST_NUMBERS.iterator(); Iterator<Integer> squares = test1.iterator(); while (numbers.hasNext()) { int n = numbers.next().intValue(); int square = squares.next().intValue(); assertEquals("elements are correct", n * n, square); } } private static final Function<Integer, Integer> SQUARE = new Function<Integer, Integer>() { public Integer apply(Integer x) { return x * x; } };

The compiler requires type arguments foranonymous inner classes; that was the bugtwo slides ago.

Page 29: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 29

© Copyright 2012, Software Alchemy

PECS Reprised

● So... what about that sorting problem? Can we create a single algorithm for all of these (and more)?

– Sort a list of integers– Sort a list of dates– Sort a list of strings

● What do these all have in common?● How does this relate to the Producer-extends,

Consumer-super principle?

Page 30: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 30

© Copyright 2012, Software Alchemy

And now the answer...

● Sorting requires that the objects in the collection are “comparable” to each other:

public static <T extends Comparable<? super T>> void sort( List<T> list) { Object[] a = list.toArray(); Arrays.sort(a); ListIterator<T> i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); } }

● ...of course, this algorithm is kind-of cheating because it really sorts an array of Objects and that method uses casts to Comparable.

Page 31: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 31

© Copyright 2012, Software Alchemy

Java Generics:a Deep Dive

Generics inFrameworks

Creating aGeneric

Framework

Odds & Sods

Mixing w/Raw Types

ErasureHistory

Wildcards

History& Theory

Complex Ex

Simple Ex

Multiple Type Params

Other Types

Creating aGeneric Class

Complex Ex

Simple Ex

PECS Reprised

Creating aGeneric Method

Enums

Simple Ex

Class

RecursiveGeneric Types

Recursive Generic Types

Page 32: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 32

© Copyright 2012, Software Alchemy

Recursive Generic Types

● “A recursive generic type is any type that makes use of a generic type that has a type argument that refers to the original type.” (me)

● This is not part of the formal definition of Java generics, but I find the concept useful.

– Because they pop-up every so often– And cause problems if you don't handle them

correctly

Page 33: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 33

© Copyright 2012, Software Alchemy

A Quasi-Recursive Generic

● The Comparable interface forms a quasi-recursive generic. For example:

public class RevenueBand implements Comparable<RevenueBand> {

private String name;private int lowerBound;private int upperBound;

@Override public int compareTo(RevenueBand that) { return this.lowerBound – that.lowerBound; }}

revBand1 = new RevenueBand("<$1M", 0, 1_000_000);revBand2 = new RevenueBand("$1M - $10M", 1_000_000, 10_000_000);revBand3 = new RevenueBand("$10M - $50M", 10_000_000, 50_000_000);assertTrue(revBand1.compareTo(revBand2) < 0);

Page 34: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 34

© Copyright 2012, Software Alchemy

Enums

● Java enums are special types that always extend Enum, which is defined as:

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {...}

● This recursive definition guarantees that no enum class may extend any other class.

– Of course, the compiler guarantees that because the extends (subclass clause) cannot be used in an enum definition:

public enum Enum { A, B, C }

Page 35: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 35

© Copyright 2012, Software Alchemy

Using Enums in Generic Methods

● The generics idiom T extends Enum<T> is used frequently in code involving enums:

public static <T extends Enum<T>> Function<String, T> valueOfFunct( final Class<T> enumClass) { return new Function<String, T>() { public T apply(String value) { return Enum.valueOf(enumClass, value); } }; }

enum MyEnum { A, B, C } @Test public void test() { Function<String, MyEnum> myFunc = valueOfFunct(MyEnum.class); assertEquals(MyEnum.B, myFunc.apply("B")); }

● Notice the use of the enumClass argument...

Page 36: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 36

© Copyright 2012, Software Alchemy

The Class Class

● The ultimate recursive generic type is Class.● From the compiler's perspective:

– MyClass.class instanceof Class<MyClass> ● Of course at run-time:

– MyClass.class instanceof Class ● ...and as you just saw classes are frequently

used to “identify” a type parameter on a generic method

Page 37: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 37

© Copyright 2012, Software Alchemy

Java Generics:a Deep Dive

Creating aGeneric

Framework

Odds & Sods

Mixing w/Raw Types

ErasureHistory

Wildcards & PECS

History& Theory

Complex Ex

Simple Ex

Multiple Type Params

Other Types

Creating aGeneric Class

Complex Ex

Simple Ex

PECS Reprised

Creating aGeneric Method

Enums

Simple Ex

Class

RecursiveGeneric Types

SpringGuava

GWT

Generics inFrameworks

Generics in Frameworks

Page 38: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 38

© Copyright 2012, Software Alchemy

Libraries to Consider

● Guava– Google's answer to Apache Commons

● Spring– The ubiquitous, light-weight, enterprise

framework for Java (Java EE replacement)● Google Web Toolkit

– Modern Java-to-JavaScript bridge framework for building advanced, single-page Web GUIs

Page 39: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 39

© Copyright 2012, Software Alchemy

The Guava Library

Page 40: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 40

© Copyright 2012, Software Alchemy

Guava Fundamentals

● Optional: holds an optional value● Predicate: an interface for a query function● Function: an interface for a generic mapping

operation– Here's a neat little higher-order operation:

public static <A, B, C> Function<A, C> compose( final Function<B, C> g, final Function<A, B> f) { return new Function<A, C>() { public C apply(A a) { return g.apply(f.apply(a)); } }; }

Page 41: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 41

© Copyright 2012, Software Alchemy

Function Composition Unit Test

enum MyEnum { A, B, C }

@Test public void test() { Function<String, MyEnum> myEnumFunc = Enums.valueOfFunction(MyEnum.class);

Function<String, String> upperCaseFunc = new Function<String, String>() { public String apply(String s) { return s.toUpperCase(); } };

Function<String, MyEnum> cleanEnumFunc = Functions.compose(myEnumFunc, upperCaseFunc);

assertEquals(MyEnum.B, cleanEnumFunc.apply("b")); }

Page 42: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 42

© Copyright 2012, Software Alchemy

Guava Collections

● Range<C extends Comparable> – A range (or "interval") defines the boundaries around a contiguous span of values of

some Comparable type; for example, "integers from 1 to 100 inclusive."

● Multiset<T> – A collection that supports order-independent equality, like Set, but may have duplicate

elements.

● Multimap<K,V> – A collection that maps keys to values, similar to Map, but in which each key may be

associated with multiple values.

● BiMap<K,V> – A bimap (or "bidirectional map") is a map that preserves the uniqueness of its values

as well as that of its keys.

Page 43: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 43

© Copyright 2012, Software Alchemy

Guava Collections

● Collections2 – transform(Collection<F>, Function<? super F, T> function)

: Collection<T> : creates a new collection of transformed elements

– filter(Collection<T>, Predicate<T> function) : Collection<T> : creates a new collection of selected elements

– And a few more...

Page 44: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 44

© Copyright 2012, Software Alchemy

Guava Collections

● Iterables – boolean all(Collection<T> c, Predicate<T> predicate)

: queries whether all elements satisfy the predicate

– boolean any(Collection<T> c, Predicate<T> predicate): queries whether any element satisfies the predicate

– T find(Collection<T> c, Predicate<T> predicate, T defValue): finds the first value that satisfies the predicate, or returns the default

– Optional<T> tryFind(Collection<T> c, Predicate<T> predicate): optionally finds the first value that satisfies the predicate

– Lots more...

Page 45: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 45

© Copyright 2012, Software Alchemy

Guava Caching

● Simple API to provide in-memory caching● Cache<K,V>: is a cache of keys to values● CacheLoader<K,V>: is a mechanism to load

cache values● Use a CacheBuilder to construct and

configure a cache

Page 46: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 46

© Copyright 2012, Software Alchemy

Guava Caching Example

private Cache<String, WarehouseHealth> pwhHealthCache; @PostConstruct private void initializeService() { int ttlInSeconds = SpringPropertyUtils.getIntProperty( PWH_HEALTH_CACHE_TTL, DEFAULT_PWH_HEALTH_CACHE_TTL); pwhHealthCache = CacheBuilder.newBuilder() .expireAfterWrite(ttlInSeconds, TimeUnit.SECONDS) .build(new CacheLoader<String, WarehouseHealth>() { @Override public WarehouseHealth load(final String key) { List<ChannelHealth> channels = pwhPrimaryDAO.getChannelHealth(); List<String> disabledProducts = pwhPrimaryDAO.getDisabledContentSets(); boolean isFileWatcherRunning = pwhPrimaryDAO.isFileWatcherRunning(); return new WarehouseHealth(channels, disabledProducts, isFileWatcherRunning); } }); }

Page 47: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 47

© Copyright 2012, Software Alchemy

The Spring Library

Page 48: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 48

© Copyright 2012, Software Alchemy

Spring's Context and Bean Ops

● ApplicationContext and BeanFactory – T getBean(String beanName, Class<T> requiredType)

: retrieves a Spring declared bean (creates it if necessary)

● BeanUtils – T instantiate(Class<T> clazz)

: creates a new instance of the bean using the no-arg constructor

– T instantiateClass(Constructor<T> clazz, Object... args): creates a new instance of a bean with a specified constructor and arguments

Page 49: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 49

© Copyright 2012, Software Alchemy

Spring's JdbcTemplate

● If you are not using an ORM tool like Hibernate or JPA, you should use Spring's JDBC template API

– Removes boilerplate JDBC code– Converts SQLException into more useful, but

silent exceptions– Allows you to focus on the SQL and data

conversion– RowMapper<T> is used to convert a single

ResultSet row into some Java object

Page 50: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 50

© Copyright 2012, Software Alchemy

Spring's JdbcTemplate

● General Queries– List<T> query(String sql, Object[] args, RowMapper<T> mapper)– T query(String sql, Object[] args, ResultSetExtractor<T> rse)

● Single Result Queries– T queryForObject(String sql, Object[] args, Class<T> clazz)– T queryForObject(String sql, Object[] args, RowMapper<T>

mapper)

● Multiple Result Queries– List<T> queryForList(String sql, Object[] args, Class<T>

elementType)

Page 51: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 51

© Copyright 2012, Software Alchemy

JdbcTemplate Example

public NovusNodeHealth getNovusHealth() { return getJdbcTemplate().queryForObject( NOVUS_HEALTH_QUERY, novusHealthMapper);}

private static final String NOVUS_HEALTH_QUERY = "SELECT novus_status, dm_load_key FROM etl_promote_status WHERE" + " dm_load_key in (SELECT max(dm_load_key) FROM etl_promote_status)";

private final RowMapper<NovusNodeHealth> novusHealthMapper = new RowMapper<NovusNodeHealth>() { public NovusNodeHealth mapRow(final ResultSet rs, final int rowNum) throws SQLException { Integer loadKey = rs.getInt("dm_load_key"); String status = rs.getString("novus_status"); return new NovusNodeHealth(status, loadKey, "NOVUS"); }};

Page 52: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 52

© Copyright 2012, Software Alchemy

The GWT Library

Page 53: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 53

© Copyright 2012, Software Alchemy

«interface»PubDatamartRPCAsync

+getStationHealth(boolean, AsyncCallback<PubDmNodeHealthDTO>) : void+stopPublishingNode( AsyncCallback<Void>) : void

User

ServerDesktop

.................................

HTTP

«interface»PubDatamartRPC

+getStationHealth(boolean) : PubDmNodeHealthDTO+stopPublishingNode() : void

«class»PubDatamartRPCImpl

+getStationHealth(boolean) : PubDmNodeHealthDTO+stopPublishingNode() : void

GWT RPC Mechanism

Page 54: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 54

© Copyright 2012, Software Alchemy

GWT RPC

● AsyncCallback is the heart of RPC mechanism:public interface AsyncCallback<T> { void onSuccess(T result); void onFailure(Throwable caught);}

● Usage: AsyncCallback<PublishingDmNodeHealthDTO> callback = new AsyncCallback<PublishingDmNodeHealthDTO>() { public void onSuccess(final PublishingDmNodeHealthDTO result) { pubHealthNode = result; // TODO refresh GUI } public void onFailure(Throwable exception) { // TODO handle exception } }; PublishingDatamartRPC.Util.getInstance() .getStationHealth(true, callback);

Page 55: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 55

© Copyright 2012, Software Alchemy

GWT DataGrid

● DataGrid<T> – A table with headers and rows– T is the type of each row

● Column<T, C>: – A single column in the grid– T is the row type and C is the column type

● Cell<C>: – Defines how the cells in the grid are rendered– C is the column type

Page 56: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 56

© Copyright 2012, Software Alchemy

GWT DataGrid Example

usersGrid = new DataGrid<UserDTO>();

Column<UserDTO, String> userIdCOL = new Column<UserDTO, String>(editUserLinkCell) { public String getValue(final UserDTO row) { return row.getUserName(); }};userNameCOL.setSortable(false);userNameCOL.setCellStyleNames("columnLeft");usersGrid.addColumn(userNameCOL, "Username");usersGrid.setColumnWidth(userNameCOL, USERNAME_COL_SIZE, Unit.PCT);

private final Cell<String> editUserLinkCell = new AnchorTextCell() { protected void handleClick(final Context ctx, final String value) { EditUserPage.makeHistoryCommand(value).invoke(); }};

Page 57: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 57

© Copyright 2012, Software Alchemy

Java Generics:a Deep Dive

Odds & Sods

Mixing w/Raw Types

ErasureHistory

Wildcards & PECS

History& Theory

Complex Ex

Simple Ex

Multiple Type Params

Other Types

Creating aGeneric Class

Complex Ex

Simple Ex

PECS Reprised

Creating aGeneric Method

Enums

Simple Ex

Class

RecursiveGeneric Types

SpringGuava

GWT

Generics inFrameworks

Multi-tierFrameworks

Simple Ex

SubsystemFrameworks

Creating aGeneric

Framework

Creating a Generic Framework

Page 58: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 58

© Copyright 2012, Software Alchemy

Building a Generic Framework

● Frameworks appear in all applications, large and small

● Look for redundant code and find a common abstraction

– Sometimes this will be an abstract superclass– Sometimes a generic class– Sometimes a generic algorithm– Sometimes a generic architectural metaphor– Sometimes a shared subsystem abstraction

Page 59: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 59

© Copyright 2012, Software Alchemy

Let's start small...

● Database query request/response that supports paging, sorting and filtering

● QueryRequest: provides input about the size and starting point of the page to query

● QueryResult<T>: provides a single page of data from the query

● PagedRowMapper<T>: extends Spring's RowMapper to provide the total count of the overall query

Page 60: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 60

© Copyright 2012, Software Alchemy

Paged Queries Framework

Database«DAO»

MyDAO

«entity»MyEntity

«value object»QueryResult

T=MyEntity

retrieve(QueryRequest):QueryResponse<MyEntity>

«Service»MyService

«helper»PagedRowMapper

T=MyEntity

«value object»QueryRequest

pageStart : intpageSize : int

totalCount : intpage : List<T>

Page 61: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 61

© Copyright 2012, Software Alchemy

The QueryResult Class

public class QueryResult<T> implements Serializable, Iterable<T> {

private final int totalCount; private final List<T> items;

public QueryResult(final int totalCountIn, final List<T> itemsIn) { this.totalCount = totalCountIn; this.items = itemsIn; }

public final int getTotalCount() { return this.totalCount; } public final List<T> getItems() { return this.items; }

@Override public final Iterator<T> iterator() { return this.items.iterator(); }}

Page 62: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 62

© Copyright 2012, Software Alchemy

The QueryResult Class

public abstract class PagedRowMapper<T> implements RowMapper<T> {

private Integer totalCount = null;

public Integer getTotalCount() { return (this.totalCount != null) ? this.totalCount : 0; }

@Override public final T mapRow(final ResultSet rs, final int rowNum) throws SQLException { if (this.totalCount == null) { this.totalCount = rs.getInt("totalCount"); } return mapEntity(rs, rowNum); }

public abstract T mapEntity(ResultSet rs, int rowNum) throws SQLException;}

Page 63: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 63

© Copyright 2012, Software Alchemy

A Multi-tier Framework

● A simple “data entry” application can take advantage of the concept of an “Entity” (with CRUD operations) across all application tiers:

DB«DAO»

MyDAO

«JPA»MyEntity

«Service»MySvc

«DTO»MyEntityDTO

User

«GWT RPC»MyRPC

«GWT»MyGUI HTTP

«helper»MyTransformer

Page 64: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 64

© Copyright 2012, Software Alchemy

A Multi-tier Framework

DB«DAO»

UserDAO

«JPA»User

T=User

«Service»UserSvc

«DTO»UserDTO

User

«GWT RPC»UserRpc

Impl«GWT»

UserPage HTTP

«helper»UserToDtoTfm

«interface»DomainEntity

DAO+create(T):ID+findById(ID):T+update(T)+delete(T)

T,ID

«class»AbstractDomainEntityDAO

T,ID=Long

T=UserT=User

«class»AbstractDomainEntityService

T

«interface»DomainEntity

Service

T

«class»AbstractDomainEntityRpcImpl

T

«interface»DomainEntity

RPC

T

«interface»UserRPC

T=User

Page 65: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 65

© Copyright 2012, Software Alchemy

A Multi-tier Framework: the Interfaces

public interface DomainEntity { public Long getId(); public void setId(Long id); public boolean isNew(); // other metadata properties}

public interface DomainEntityDAO<T extends DomainEntity, ID extends Serializable> { public ID create(T entity); public T findById(ID id); public boolean delete(T entity); public void update(T entity);}

public interface DomainEntityService<T extends DomainEntity> { public EntityResponse<T> create(T entity); public EntityResponse<T> retrieveById(Long entityId); public ServerResponse update(T entity); public ServerResponse delete(Long entityId);}

Page 66: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 66

© Copyright 2012, Software Alchemy

A Multi-tier Framework: the Interfaces

public interface EntityDTO extends Model, IsSerializable { public static enum Depth { SURFACE, SUMMARY, TREE, DEEP }; public Long getId(); public void setId(Long id); public Depth getDepth(); public void setDepth(Depth depth); public boolean isNew(); public void merge(EntityDTO dto);}

public interface DomainEntityRPC<DTO extends EntityDTO> { public abstract GuiEntityResponse<DTO> create(DTO entity); public abstract GuiEntityResponse<DTO> retrieveById(Long id); public abstract GuiServerResponse update(DTO entity); public abstract GuiServerResponse delete(Long id);}

public interface DomainEntityRpcAsync<DTO extends EntityDTO> { void create(DTO entity, AsyncCallback<GuiEntityResponse<DTO>> c); void retrieveById(Long id, AsyncCallback<GuiEntityResponse<DTO>> c); void update(DTO entity, AsyncCallback<GuiServerResponse> c); void delete(Long id, AsyncCallback<GuiServerResponse> c);}

Page 67: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 67

© Copyright 2012, Software Alchemy

Subsystem Framework Example

● The Incentives framework supports three concrete subsystems in a financial application

– Apps main function is supply chain analysis● Sales line item data● Plus lots of reference data: products, pricing

catalogs, customers, etc– Incentives provides decision support

● SPA: special pricing catalog assignment● Rebates: identify SLIs for rebates to resellers● SCA: sales rep commissions

Page 68: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 68

© Copyright 2012, Software Alchemy

Incentives Framework Concepts

Incentive'sDomainModel

mind-map

Program

Rules

Association

CalcResult

Transaction

Entity

Metadata

GUI Summaryobjects

Contains inference andcalculation rules.

Inference rulesgenerate associations.

Calculation rulesgenerate calculation

results.

Page 69: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 69

© Copyright 2012, Software Alchemy

Incentives “Programs” Flow

Eligibility

Association<Txn,Program>

Nucleus

Assignment

Association<Txn,Entity>

Calculation

CalculationResult

Txn

Txn

Entity

Adjustment

CalculationResult#AuditRecord

Entity

Page 70: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 70

© Copyright 2012, Software Alchemy

Incentives Analysis Model

RebatesExecutionService

TransactionService

AbstractProgramService

DataService

ProgramSummary

ProgramReview

ProgramEditor

ProgramTest

RebatesProgramDAO

DataServiceDAO

TransactionDAO

RebatesExecutionDAO

EligibilityEditor

ReRater

Page 71: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 71

© Copyright 2012, Software Alchemy

Incentives Execution Services

«interface»IncentiveExecution

Service

«nucleusService»RebatesExecution

ServiceImpl

«nucleusService»SpaExecutionServiceImpl

T extends Entity

«interface»RebatesExecution

Service

«abstract»AbstractIncentiveExecutionService

T extends Entity

T=ProfileEntity

T=ProfileEntity T=SpaCatalogRecord

«interface»Service

«abstract»AbstractBaseService

+generatePayoutPayment+getPaymentHistory

Page 72: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 72

© Copyright 2012, Software Alchemy

Java Generics:a Deep Dive

Mixing w/Raw Types

ErasureHistory

Wildcards & PECS

History& Theory

Complex Ex

Simple Ex

Multiple Type Params

Other Types

Creating aGeneric Class

Complex Ex

Simple Ex

PECS Reprised

Creating aGeneric Method

Enums

Simple Ex

Class

RecursiveGeneric Types

SpringGuava

GWT

Generics inFrameworks

Multi-tierFrameworks

Simple Ex

SubsystemFrameworks

Creating aGeneric

Framework

ReflectionWhen not touse generics

TipsOdds & Sods

Odds & Sods

Page 73: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 73

© Copyright 2012, Software Alchemy

Tips from Effective Java

● Don't use raw types in new code● Eliminate unchecked warnings

– Removed raw types– Or suppress

● Prefer lists to arrays– Arrays are reified (runtime value checks);

whereas lists are erased (compile-time checks)● Favor generic types

– Courageously create generic types and methods

Page 74: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 74

© Copyright 2012, Software Alchemy

Tips from Effective Java

● Favor generic methods● Use bounded wildcards to increase API

flexibility– PECS principle

● Consider type-safe heterogeneous containers– Example API:

public interface Favorites { public <T> void putFavorite(Class<T> type, T instance); public <T> T getFavorite(Class<T> type);}

Page 75: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 75

© Copyright 2012, Software Alchemy

When NOT to use Generics

● Don't be afraid of complex typed data structures, but...

● Remember that primitives are stored as wrapped objects inside of generic collections.

● Complex computations over such complex data structures can lead to:

– Lots of unnecessary auto-boxing– Thus hinders performance

● But... the first rule of optimization is ???

Page 76: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 76

© Copyright 2012, Software Alchemy

Example

private void processAverages() { int dayCount = 1; Map<PathwayStation, Long> stationTotals = new EnumMap<>(PathwayStation.class); Map<PathwayStation, Map<Category, Long>> categoryTotals = new EnumMap<>(PathwayStation.class); // start with today's stats for (PathwayStation s : PathwayStation.values()) { stationTotals.put(s, dailyLoadStats.getStationTotal(s)); Map<Category, Long> catTotalsByStation = new HashMap<>(); categoryTotals.put(s, catTotalsByStation); for (Category c : pathwayConfig.getCategories()) { catTotalsByStation.put(c, dailyLoadStats.getCategoryTotal(s, c)); } } // process the averages for (DailyLoadStatistics dls : loadStatsHistory) { cayCount++; // accumulate station totals for (PathwayStation s : PathwayStation.values()) { stationTotals.put(s, stationTotals.get(s)+dls.getStationTotal(s)); // accumulate category totals Map<Category, Long> catTotalsByStation = categoryTotals.get(s); for (Category c : pathwayConfig.getCategories()) { catTotalsByStation.put(c, catTotalsByStation.get(c) +dls.getCategoryTotal(s, c)); // MORE...

Page 77: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 77

© Copyright 2012, Software Alchemy

Example Refactored

private void processAverages() { int dayCount = 1; List<Category> categories = pathwayConfig.getCategories(); long[] stationTotals = new long[PathwayStation.values().length]; long[][] categoryTotals = new long[PathwayStation.values().length][]; // start with today's stats for (PathwayStation s : PathwayStation.values()) { stationTotals[s.ordinal()] = dailyLoadStats.getStationTotal(s); // categories long[] catTotalsByStation = new long[categories.size()]; categoryTotals[s.ordinal()] = catTotalsByStation; int cc = 0; for (Category c : pathwayConfig.getCategories()) { catTotalsByStation[cc++] = dailyLoadStats.getCategoryTotal(s, c); } } // process the averages for (DailyLoadStatistics dls : loadStatsHistory) { dayCount++; // accumulate station totals for (PathwayStation s : PathwayStation.values()) { stationTotals[s.ordinal()] += dls.getStationTotal(s); // accumulate category totals // MORE... you get the idea

Page 78: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 78

© Copyright 2012, Software Alchemy

Reflection

● Because generic type arguments are erased at runtime, you cannot perform reflection on an object instance.

● However, you can perform reflection on the type parameters of generic classes and methods.

Page 79: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 79

© Copyright 2012, Software Alchemy

Reflection Example

class GenericClass<T extends Enum<T>, N extends Number> { }

public class ReflectionTest { @Test public void test1() { Class<?> clazz = GenericClass.class; TypeVariable<?>[] typeParams = clazz.getTypeParameters(); // test type params TypeVariable<?> first = typeParams[0]; assertEquals("T", first.getName()); Type firstBoundsType = first.getBounds()[0]; assertTrue("first param type is bound by a parameterized type", (firstBoundsType instanceof ParameterizedType)); assertEquals(Enum.class, ((ParameterizedType)firstBoundsType).getRawType()); TypeVariable<?> second = typeParams[1]; assertEquals("N", second.getName()); Type secondBoundsType = second.getBounds()[0]; assertTrue("second param type is bound by a standard type", !(secondBoundsType instanceof ParameterizedType)); assertEquals(Number.class, secondBoundsType); }}

Page 80: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 80

© Copyright 2012, Software Alchemy

Java Generics:a Deep Dive

Mixing w/Raw Types

ErasureHistory

Wildcards & PECS

History& Theory

Complex Ex

Simple Ex

Multiple Type Params

Other Types

Creating aGeneric Class

Complex Ex

Simple Ex

PECS Reprised

Creating aGeneric Method

Enums

Simple Ex

Class

RecursiveGeneric Types

SpringGuava

GWT

Generics inFrameworks

Multi-tierFrameworks

Simple Ex

SubsystemFrameworks

Creating aGeneric

Framework

ReflectionWhen not touse generics

TipsOdds & Sods

Q & A

Page 81: Java Generics: a deep dive

RJUG : 12-Dec-2012

Bryan Basham – Java Generics: a Deep Dive Slide 81

© Copyright 2012, Software Alchemy

Resources

● Wikipedia

● Official Java Tutorial

● Generics in the Java Programming Language (tutorial by Gilad Bracha)

● Angelika Langer's Java Generics FAQ

● JSR 14: Add Generic Types to the Java Programming Language

● Book: Java Generics (O'Reilly Media)

● More Wikipedia:

– Type Systems – Generic Programming

● StackOverflow on PECS principle