Generics are one of the most complex features of Java. They are often poorly understood and lead to confusing errors. Unfortunately, it won’t get easier. Java 10, release planned for 2018, extends Generics. It’s now time to understand generics or risk being left behind.
We start by stepping back into the halcyon days of 2004 and explain why generics were introduced in the first place back. We also explain why Java’s implementation is unique compared to similar features in other programming languages.
Then we travel to the present to explaining how to make effective use of Generics. We then explore various entertaining code examples and puzzlers of how Generics are used today.
Finally, this talk sheds light on the planned changes in Java 10 with practical code examples and related ideas from other programming languages. If you ever wanted to understand the buzz around higher kinded types or declaration site variance now is your chance!
9. Intersection
A ∩ B = elements has to be a member of both A and B
Intersection Type
<T extends A & B> = T has to extend A and B
10. <T extends Object & Comparable<? super T>>
T max(Collection<? extends T> coll)
11. A Confusing Intersection Type
<T extends Object & Comparable<? super T>>
T max(Collection<? extends T> coll)
intersection
12. Signature pre-generics
public static Object max(Collection coll)
● max is stuck with this signature to preserve binary
compatibility.
● Can only find the max if the objects are Comparable
13. Type erasure
<T extends Comparable<? super T>>
T max(Collection<? extends T> coll)
Comparable max(Collection coll)
javac compilation
14. Type erasure with intersection
<T extends Object & Comparable<? super T>>
T max(Collection<? extends T> coll)
Object max(Collection coll)
javac compilation
15. Serializable lambdas
<T, U extends Comparable<? super U>> Comparator<T>
comparing(Function<? super T, ? extends U> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator<T> & Serializable)
(c1, c2) ->
keyExtractor.apply(c1)
.compareTo(keyExtractor.apply(c2));
}
19. Examples
<T> List<T> unmodifiableList(List<? extends T> list)
<T> int binarySearch(List<? extends T> list, T key,
Comparator<? super T> c)
<T> int binarySearch(List<? extends Comparable<?
super T>> list, T key)
21. ? super
Commonly used for Functional Interfaces
Comparator<Foo>
always Comparator<? super Foo>
int compare(T o1, T o2);
Comparator<Message> <: Comparator<? super EmailMessage>
Predicate<Foo>
always Predicate<? super Foo>
boolean test(T t);
Predicate<Message> <: Predicate<? super EmailMessage>
22. Adoption and use of Java generics
90% generics use with Collections
○ List<String>, ArrayList<String>,
○ HashMap<String,String>, Set<String>
wildcards 10%
○ Class<?>
http://www.cc.gatech.edu/~vector/papers/generics2.pdf
27. Declaration-site variance
● User-site variance
○ variance complexity pushed to users
○ can add more verbosity due to annotations
● Declaration-site variance
○ variance complexity pushed to library level
○ List needs to be split in ReadOnly, WriteOnly
○ Adopted by C#, Scala
Improved variance for generic classes and interfaces
http://openjdk.java.net/jeps/8043488
28. Value Types
● “codes like a class, works like an int”
● No Identity
● Just a struct of values
29. Compactness (Less memory)
● No Mark Word
○ Locking
● No klass pointer
● Saving 8-16 bytes depending upon architecture/VM
31. BUT there’s yet generics more complexity
● No Identity, reference equality, locking or condition variables
● So we need to add a new concept to generics
● Explicitly need to opt your generic type into any value:
class ArrayList<any T> implements List<T>
32. Primitive specialisation
List<int> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
State of the Specialization
http://cr.openjdk.java.
net/~briangoetz/valhalla/specialization.html
33. Of interest …
● Unbounded Wildcards
● Type Bounds
● Erasure Problems & Advantages
● Static safety failures
● Other Languages & Features (Lambda Cube)
● Source Code
○ https://github.com/RichardWarburton/generics-examples
34. Conclusions
● Usage patterns change as other features are added
● Generics usage continues to increase in both scale and
complexity
● Most of the complexity burden is on library authors