©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the...

30
©SoftMoore Consulting Slide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” Cay Horstmann

Transcript of ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the...

Page 1: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 1

Generics

“Generics constitute the most significant change in the Java programming language since the 1.0 release.”

– Cay Horstmann

Page 2: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 2

Generics

• Added to Java in version 5

• Similar to C++ templates and Ada generics

• Support typed collection classes and typed methods

• Reduce the need for casting

• Provide additional compile-time checking for code correctness

• Characteristics– easy to use– not easy to implement

Page 3: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 3

Generics Example

• Before Java 5 and genericsList customers = new LinkedList();...Customer c = (Customer) customers.get(0);

• Using genericsList<Customer> customers = new LinkedList<Customer>();...Customer c = customers.get(0); // no cast necessary

Page 4: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 4

Generics

• Allow a type or method to operate on objects of various types while providing compile-time type safety.

• Add compile-time type safety to the Collections Framework

• Eliminate the drudgery of casting.

• One of the most requested new features of Java 5

Page 5: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 5

A Simple Generic Class

public class Pair<T, S> { private T first; private S second;

public Pair(T first, S second) { this.first = first; this.second = second; }

public T getFirst() { return first; }

public S getSecond() { return second; } }

Page 6: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 6

Using Class Pair

• Creating an instance of the generic classPair<String, BankAccount> namedAcct = new Pair<String, BankAccount>("John", acct);

• Since Java 7, the second set of type arguments can be omitted from the constructor as long as the compiler can determine or infer the type arguments from the context.Pair<String, BankAccount> namedAcct = new Pair<>("John", acct);

• This pair of angle brackets, <>, is informally called the diamond.

Page 7: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting

Using Class Pair(continued)

• The generic class Pair<T, S> can be used– as the type of a method parameter– as the return type of a method

• Note that both generic parameters can have the same type, as in Pair<String, String>.

Slide 7

Page 8: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 8

Example: Defining a Generic Class

Excerpt from the definitions of the class List<E> andIterator<E> in package java.util

public interface List<E> { void add(E x); Iterator<E> iterator(); }

public interface Iterator<E> { E next(); boolean hasNext(); }

formal type parameter

Page 9: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 9

Type Variables

• A generic class or interface is declared with a type variable (often simply E) enclosed in angle brackets.

• The type variable denotes an element type that can be used within the generic class.

• A generic class can be instantiated with any class or interface typeList<BankAccount> accounts = new

ArrayList<BankAccount>();

List<Comparable> comps = new ArrayList<Comparable>();

• A generic class cannot be instantiated with a primitive type such as int or double (use wrapper classes).

Page 10: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 10

Naming Type Variables

Type Variable Name

Meaning

E Element type in a collection

K Key type in a map

V Value type in a map

T, S, U General types

Page 11: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 11

Advantages of Generics

• More readable code

• More correct code– can’t add a String to a list instantiated to hold bank accounts– checking performed by the compiler rather than at run time.

But the price we pay is language complexity.

Page 12: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 12

Erasure

• Intuitively, List<String> behaves like a version ofList where E has been uniformly replaced by String.

• This intuition can be helpful, but it’s also misleading.

• Generics are implemented by the Java compiler as a front-end conversion called erasure.

• Erasure gets rid of (or erases) all generic type information, resulting in raw type, a list of Object. The checks for correctness and consistency are performed only by the compiler.

Page 13: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 13

Example: Pair Class After Erasure

public class Pair { private Object first; private Object second;

public Pair(Object first, Object second) { this.first = first; this.second = second; }

public Object getFirst() { return first; } public Object getSecond() { return second; } }

Page 14: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

Interface Iterable<E>

package java.lang;

import java.util.Iterator;

public interface Iterable<T> { Iterator<T> iterator(); }

©SoftMoore Consulting Slide 14

Implementing this interface allows an objectto be the target of a “forEach” loop.

Page 15: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 15

Enhanced “for” Loop

• Defined in Java 5 (a.k.a. Java 1.5)

• Syntaxfor (Classname variable : collection) statement; // may be a compound statement

• Works for collections and arrays– Collection must implement the Iterable interface

• Reduces the need for working with iterators and index variables.

Page 16: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 16

Example: Enhanced “for” Loop

• Assume we have a list of Customer objectsList<Customer> customers = new ArrayList<Customer>();

• Without the enhanced “for” loop (before Java 5)Iterator iter = customers.iterator();while (iter.hasNext()) { Customer c = (Customer) iter.next(); System.out.println(c); }

• Using the enhanced “for” loopfor (Customer c : customers) System.out.println(c);

Page 17: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 17

Example: Using Enhanced “for” Loopwith Primitive Types and Arrays

int sum(int[] a) { int result = 0;

for (int i : a) result += i;

return result; }

Page 18: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 18

Autoboxing

• Java makes a distinction between primitive types (int, double, char, etc.) and classes.

• Problem: Can’t put primitive types into collections.

• Possible solutions prior to Java 5– use wrapper classes (Integer, Double, Character, etc.)– write your own List class to handle primitive types

(separate class for each type)

• With autoboxing, the compiler performs automatic conversions between primitive types and their corresponding wrapper classes.

Page 19: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 19

Example: Autoboxing

• Without autoboxing (before Java 5)List list = new LinkedList();list.add(new Integer(13));...int n = ((Integer)(list.get(0))).intValue();

• With autoboxingList<Integer> list = new LinkedList<Integer>();list.add(13);...int n = list.get(0);

Page 20: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 20

Using Autoboxing

• The wrapper classes are still used. The compiler automatically converts between primitive classes and wrapper classes.

• Acceptable performance for occasional use

• Not appropriate for performance-critical applications and scientific numerical computing

Page 21: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 21

Constraining Type Variables

• Type variables can be constrained with boundspublic static <E extends Comparable<E>> E min(E[] a) { ... }

• “extends” actually means “extends” or “implements”.

• Bounds can be either classes or interfaces

• Can be called with String[] since String implements Comparable

• You can specify more than one type bound<E extends Comparable<E> & Cloneable>

Page 22: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 22

Generics and Subtyping

• Consider the following code:public class BankAccount { … }public class SavingsAccount extends BankAccount { … }List<BankAccount> a1 = new ArrayList<BankAccount>();List<SavingsAccount> a2 = new ArrayList<SavingsAccount>();

• We can add an object of class SavingsAccount to the list, but List<SavingsAccount> is not a subclass of List<BankAccount>.

Page 23: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 23

Wildcards

• It is possible to declare a collection whose element type matches anything.void printCollection(Collection<?> c) { for (Object e : c) { System.out.println(e); } }

• Collection<?> is a “collection of unknown”

Page 24: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 24

Using Wildcards

• Given a List<?>, we can call get() and make use of the result. The result type is an unknown type, but we always know that it is an object.

• It is therefore safe to assign the result of get() to a variable of type Object or pass it as a parameter where the type Object is expected.

Page 25: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 25

Bounded Wildcards: Motivation

• Assume we have an abstract class Shape and several subclasses of Shape (Circle, Rectangle, etc.).

• Method drawAll() will draw all shapes in a list.public void drawAll(List<Shape> shapes) { for (Shape s: shapes) s.draw(); }

• However, drawAll() will not accept List<Circle> as a valid type parameter.

Page 26: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 26

Bounded Wildcards

• We can rewrite method drawAll() using a bounded wildcard so that it will accept List<Circle> as a type parameter.public void drawAll(List<? extends Shape> shapes) { for (Shape s: shapes) s.draw(); }

Page 27: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 27

Generic Methods: Motivation

• Suppose you want to create a method that takes an array of objects and a collection and puts all objects in the array into the collection.static void copy (Object[] source, Collection<?> destination) { for (Object o : source) destination.add(o); // compile time error }

• Problem: You cannot add objects into a collection of unknown type.

Page 28: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 28

Generic Method

• Method with a type variablestatic <E> void print(List<E> l) ...

• Can be defined inside ordinary or a generic classes

• Can be static or non-static

• Compiler infers the actual type when the method is called – not explicitly expressed by the programmer.List<BankAccount> accounts = new LinkedList<BankAccount>();...print(accounts);

Page 29: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 29

Using Generic Methods

• We can solve the copy problem using a generic methodstatic <T> void copy(T[] source, Collection<T> destination) { for (T o : source) destination.add(o); // Correct }

• Calling the generic methodList<BankAccount> accts = new LinkedList<BankAccount>();...BankAccount[] actArray = new BankAccount[100];...copy(actArray, accts); // T inferred to be BankAccount

Page 30: ©SoftMoore ConsultingSlide 1 Generics “Generics constitute the most significant change in the Java programming language since the 1.0 release.” – Cay Horstmann.

©SoftMoore Consulting Slide 30

Using Legacy Code with Generics

• When a generic type like List is used without a type parameter, it is a raw type (type Object).

• Using a raw type generates an unchecked warning, not an error.List list = new ArrayList(); // use only for

compatibility // with legacy codelist.add("Hello");list.add(new Date());

• The programmer is responsible for checking that the code is correct.