Slide 1

Slide 1 text

Java Generics When, how and why by Gayashan Amarasinghe Software Engineer - WSO2 Inc

Slide 2

Slide 2 text

History Introduced in Java 5 Heavily utilized in the Collections API Also known as “Parameterized Types”

Slide 3

Slide 3 text

Before Generics List coins = new ArrayList(); // contains only coins coins.add(new Coin(2)); coins.add(new Stamp()); Coin coin = (Coin) coins.get(0); Stamp stamp = (Stamp) coins.get(1); What if, Coin coin = (Coin) coins.get(1); // throws ClassCastException

Slide 4

Slide 4 text

Before Generics - Issues ● You can add any object type to any collection. ● Only when you try to retrieve, in runtime you will detect errors. (ClassCastException) ● Now you’ll have to search through the code base to identify where you have put a stamp into a coins collection!

Slide 5

Slide 5 text

After Generics List coins = new ArrayList(); coins.add(new Coin(2)); coins.add(new Stamp()); // compile error Coin coin = coins.get(0); Stamp stamp = coins.get(1); // compile error What if, Coin coin = coins.get(1); // compile error

Slide 6

Slide 6 text

After Generics Compile time error detection - modern IDEs utilize this heavily to guide No manual casts are needed More expressive code

Slide 7

Slide 7 text

Raw types vs Generics 1. List objects = new ArrayList(); 2. List objects = new ArrayList(); [1] has opted out of generic type checking. [2] has explicitly told the compiler that it can hold objects of any type. ALWAYS use generics instead of Raw types! public static void main(String[] args) { List strings = new ArrayList(); unsafeAdd(strings, new Integer(42)); String s = strings.get(0); // Compiler-generated cast } private static void unsafeAdd(List list, Object o) { list.add(o); // unchecked call to add(E) }

Slide 8

Slide 8 text

Subtyping rules List objects = new ArrayList(); List strings = new ArrayList(); objects = strings; // legal operation But, List objects = new ArrayList(); List strings = new ArrayList(); objects = strings; // compile error

Slide 9

Slide 9 text

Subtyping rules List is a sub type of List But List is not a subtype of List For any two distinct types Type1 and Type2 , List is neither a subtype nor a supertype of List.

Slide 10

Slide 10 text

Introducing Wildcards static void printElements(List list) { for (Object obj : list){ System.out.println(obj); } } This works, but this is very dangerous. Why?

Slide 11

Slide 11 text

Introducing Wildcards Can we do this? static void printElements(List list) { for (Object obj : list){ System.out.println(obj); } } Remember subtyping rules? List strings = new ArrayList(); printElements(strings); // compile error

Slide 12

Slide 12 text

Introducing Wildcards static void printElements(List list) { for (Object obj : list){ System.out.println(obj); } } ? is the wildcard type Wildcards - type safe and flexible

Slide 13

Slide 13 text

Unbounded Wildcards ● Collection is a collection of some unknown type ● Most general parameterized type ● You can’t put any element (other than null) into a Collection ● You can’t assume anything of the type of the object you get out as well. ○ You can only treat them as Objects

Slide 14

Slide 14 text

Bounded Wildcards ● Wildcard types can have upper and lower bounds ● A List is a List of items that have unknown type but are all at least Shapes. - upper bound ● A List is a List of items that have unknown type but are all at most Shapes. - lower bound

Slide 15

Slide 15 text

Bounded Wildcards Demo

Slide 16

Slide 16 text

PECS principle Producer extends, Consumer super Case 1: You want to go through the collection and do things with each item. Then the collection is a producer, so you should use Collection. Case 2: You want to add things to the collection. Then the collection is a consumer, so you should use Collection.

Slide 17

Slide 17 text

Generic methods Methods can be parameterized as well! public static Set union(Set s1, Set s2) Type Parameter list ● The compiler figures out the type parameter by examining the types of method argument - via type inference Type parameter representing element type

Slide 18

Slide 18 text

Generic methods ● Type inference Set fruits = new HashSet(Arrays. asList(“apple”, “orange”)); Set veges = new HashSet(Arrays. asList(“carrot”, “cabbage”)); Set combined = union(fruits, veges);

Slide 19

Slide 19 text

Generic methods - more static void fromArrayToCollection(Object[] a, Collection c) { for (Object o : a) { c.add(o); // compile error } } Way to fix this - use generic types, static void fromArrayToCollection(T[] a, Collection c) { for (T o : a) { c.add(o); // Correct } }

Slide 20

Slide 20 text

Generic methods - when? If return type doesn’t depend on type parameter and, neither any other argument in the method - use Wildcards Need to express dependencies among the types of one or more arguments to a method and/or its return type - use generic methods String[] sa = new String[100]; Collection cs = new ArrayList(); // T inferred to be String fromArrayToCollection(sa, cs);

Slide 21

Slide 21 text

How Generics are Implemented ● Rather than change every JVM between Java 1.4 and 1.5, they chose to use erasure. ● After compiler does the type checking it discards the generics, and JVM never sees them! ● Works similar to this - ○ List becomes List ○ Use of type variables are replaced by their upper bound (usually Object) ○ Casts are inserted to preserve type correctness

Slide 22

Slide 22 text

Pros and Cons of Erasure Good - Backward compatibility is preserved. (can be used with legacy non-generic libraries) Bad - Cannot find out what type a generic class is using, at run-time. Eg: class Sample{ void method(Object item){ if(item instanceof T) { ... } // compile error T anotherItem = new T(); // compile error T[] itemArray = new T[5]; // compile error } }

Slide 23

Slide 23 text

Summary Use Generics ALWAYS! - Don’t use raw types Favour generic classes - Object-based collection Favour generic methods - static utility methods Use bounded wildcards to increase API flexibility Do not ignore compiler warnings!

Slide 24

Slide 24 text

Q & A

Slide 25

Slide 25 text

Thank You! :)