Chapter 21 Generics

46
1 Chapter 21 Generics Chapter20 Lists,Stacks,Q ueues, Trees, and H eaps Chapter21 G enerics Chapter22 Java C ollectionsFram ew ork Chapter23 A lgorithm Efficiency and Sorting Chapter11 O bject-O riented D esign Chapter19 R ecursion

description

Chapter 21 Generics. Objectives. To use generic classes and interfaces (§21.2). To declare generic classes and interfaces (§21.3). To understand why generic types can improve reliability and robustness (§21.3). To declare and use generic methods and bounded generic types (§21.4). - PowerPoint PPT Presentation

Transcript of Chapter 21 Generics

Page 1: Chapter 21 Generics

1

Chapter 21 Generics

Chapter 20 Lists, Stacks, Queues, Trees, and Heaps

Chapter 21 Generics

Chapter 22 Java Collections Framework

Chapter 23 Algorithm Efficiency and Sorting

Chapter 11 Object-Oriented Design

Chapter 19 Recursion

Page 2: Chapter 21 Generics

2

Objectives To use generic classes and interfaces (§21.2). To declare generic classes and interfaces (§21.3). To understand why generic types can improve reliability

and robustness (§21.3). To declare and use generic methods and bounded generic

types (§21.4). To use raw types for backward compatibility (§21.5). To know wildcard types and understand why they are

necessary (§21.6). To understand that all instances of a generic class share the

same runtime class file (§21.7). To convert legacy code using JDK 1.5 generics (§21.8). To design and implement a generic matrix class (§21.9).

Page 3: Chapter 21 Generics

Example: Pre_Java5

3

Page 4: Chapter 21 Generics

See these warnings before?

4

Warnings from last compilations<program> uses unchecked or unsafe operationsRecompile with –Xlint unchecked for details

Page 5: Chapter 21 Generics

5

Why Do You Get a Warning?public class TestArrayList { public static void main(String[] args) { // Create a list to store cities java.util.ArrayList cityList = new java.util.ArrayList(); // Add some cities in the list cityList.add("London"); }} To understand the compile

warning on this line, you need to learn JDK 1.5 generics.

Page 6: Chapter 21 Generics

6

ArrayListpublic ArrayList() Constructs an empty list with an initial capacity of ten.

addpublic boolean add(E e) Appends the specified element to the end of this list. Specified by:add in interface Collection<E>Specified by:add in interface List<E>Overrides:add in class AbstractList<E> Parameters:e - element to be appended to this list Returns:true (as specified by Collection.add(E))

Page 7: Chapter 21 Generics

7

Generic Type

package java.lang; public interface Comaprable { public int compareTo(Object o) }

package java.lang; public interface Comaprable<T> { public int compareTo(T o) }

(a) Prior to JDK 1.5 (b) JDK 1.5

Generic Instantiation Runtime error

Compile error

Comparable c = new Date(); System.out.println(c.compareTo("red"));

(a) Prior to JDK 1.5

Comparable<Date> c = new Date(); System.out.println(c.compareTo("red"));

(b) JDK 1.5

Improves reliabilityRestricts to type Date

Page 8: Chapter 21 Generics

8

Generic ArrayList in JDK 1.5 java.util.ArrayList

+ArrayList() +add(o: Object) : void +add(index: int, o: Object) : void +clear(): void +contains(o: Object): boolean +get(index: int) : Object +indexOf(o: Object) : int +isEmpty(): boolean +lastIndexOf(o: Object) : int +remove(o: Object): boolean +size(): int +remove(index: int) : boolean +set(index: int, o: Object) : Object

java.util.ArrayList<E>

+ArrayList() +add(o: E) : void +add(index: int, o: E) : void +clear(): void +contains(o: Object): boolean +get(index: int) : E +indexOf(o: Object) : int +isEmpty(): boolean +lastIndexOf(o: Object) : int +remove(o: Object): boolean +size(): int +remove(index: int) : boolean +set(index: int, o: E) : E (a) ArrayList before JDK 1.5 (b) ArrayList in JDK 1.5

Page 9: Chapter 21 Generics

9

Fix the Warning in BJ_Java5import java.util.*;public class TestArrayListNew { public static void main(String[] args) { ArrayList<String> cityList = new ArrayList<String>(); // Add some cities in the list cityList.add("London"); }}

Tells compiler that Strings are expected.No compile warning on this line.

Page 10: Chapter 21 Generics

10

No Casting Needed – Boxing and Unboxing

ArrayList<Double> list = new ArrayList<Double>();

list.add(5.5); // 5.5 is automatically converted to new Double(5.5)

list.add(3.0); // 3.0 is automatically converted to new Double(3.0)

Double doubleObject = list.get(0); // No casting is needed

double d = list.get(1); // Automatically converted to double

Page 11: Chapter 21 Generics

11

Declaring Generic Classes and Interfaces GenericStack<E>

-elements: E[] -size: int

+GenericStack() +GenericStack(initialCapacity:

int) +getSize(): int +peek(): E +pop(): E +push(o: E): E +isEmpty(): boolean

Creates an empty stack with default initial capacity 16. Creates an empty stack with the specified initial

capacity. Returns the number of elements in this stack. Returns the top element in this stack. Returns and removes the top element in this stack. Adds a new element to the top of this stack. Return true if the stack is empty.

An array to store elements. The number of the elements in this stack.

BJ_GenericStack

Page 12: Chapter 21 Generics

To print elements of different types Before Java5

12

public class PreJava5MethodDemo {

public static void main(String[] args ) { Integer[] integers = {1, 2, 3, 4, 5}; String[] strings = {"London", "Paris", "New York", "Austin"};

PreJava5MethodDemo.print(integers); PreJava5MethodDemo.print(strings); } // Provide two overloaded methods public static void print(Integer[] list) { // . . . }

public static void print(String[] list) { // . . . }}

Page 13: Chapter 21 Generics

To print elements of different types From Java5 with Generic Methods

13

public class GenericMethodDemo { public static void main(String[] args ) { Integer[] integers = {1, 2, 3, 4, 5}; String[] strings = {"London", "Paris", "New York", "Austin"};

GenericMethodDemo.<Integer>print(integers); GenericMethodDemo.<String>print(strings); } public static <E> void print(E[] list) { for (int i = 0; i < list.length; i++) System.out.print(list[i] + " "); System.out.println(); }}

Page 14: Chapter 21 Generics

14

Generic Methods public static <E> void print(E[] list) { for (int i = 0; i < list.length; i++) System.out.print(list[i] + " "); System.out.println(); }// versus

public static void print(Object[] list) { for (int i = 0; i < list.length; i++) System.out.print(list[i] + " "); System.out.println(); }

Page 15: Chapter 21 Generics

Can I specify the type as say <F>?

15

public class GenericMethodDemoF { public static void main(String[] args ) { Integer[] integers = {1, 2, 3, 4, 5}; String[] strings = {"London", "Paris", "New York", "Austin"};

GenericMethodDemo.<Integer>print(integers); GenericMethodDemo.<String>print(strings); }

public static <F> void print(F[] list) { for (int i = 0; i < list.length; i++) System.out.print(list[i] + " "); System.out.println(); }}

Page 16: Chapter 21 Generics

Can I specify subtypes?

16

Suppose we want to restrict to Circle and Rectangle objects only in class BoundedTypeDemo

Page 17: Chapter 21 Generics

17

Bounded Generic Typepublic static void main(String[] args ) { Rectangle rectangle = new Rectangle(2, 2); Circle9 circle = new Circle9(2); System.out.println("Same area? " + equalArea(rectangle, circle));}// Want to restrict to subclasses of GeometricObjectpublic static <E extends GeometricObject> boolean equalArea(E object1, E object2) { return object1.findArea() == object2.findArea();}

Page 18: Chapter 21 Generics

Bounded Generic Type

See BJ_BoundedType

18

Page 19: Chapter 21 Generics

19

Raw Type and Backward Compatibility

// raw typeGenericStack stack = new GenericStack();

This is roughly equivalent to GenericStack<Object> stack = new GenericStack<Object>();

Page 20: Chapter 21 Generics

20

Raw Type: Compile? Run? Safe? Why?

Max.max("Welcome", 23);

// Max.java: Find a maximum objectpublic class Max { /** Return the maximum between two objects */ public static Comparable max(Comparable o1, Comparable o2) { if (o1.compareTo(o2) > 0) return o1; else return o2; } // see also the code in BJ_Max around compareTo public static void main(String[] args) {

System.out.println("max is " + Max.max("Welcome", 23)); }}

Page 21: Chapter 21 Generics

Runtime Exception on running class Max:

21

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at java.lang.String.compareTo(String.java:92) at Max.max(Max.java:9) at Max.main(Max.java:17)

Page 22: Chapter 21 Generics

22

Make it Safe – See class BJ_Max1

Max.max("Welcome", 23);

// Max1.java: Find a maximum objectpublic class Max1 { /** Return the maximum between two objects */ public static <E extends Comparable<E>> E max(E o1, E o2) { if (o1.compareTo(o2) > 0) return o1; else return o2; }}

Page 23: Chapter 21 Generics

23

Compilation error instead

Page 24: Chapter 21 Generics

24

Wildcards

WildCardDemo1

Why wildcards are necessary? See this example.

? unbounded wildcard ? Extends T bounded wildcard ? Super T lower bound wildcard:

WildCardDemo2 WildCardDemo3

Page 25: Chapter 21 Generics

25

Page 26: Chapter 21 Generics

WildCardDemo1

26

public class WildCardDemo1 { public static void main(String[] args ) { GenericStack<Integer> intStack = new GenericStack<Integer>(); intStack.push(1); // 1 is autoboxed into new Integer(1) intStack.push(2); intStack.push(-2);

System.out.println("The max number is " + max(intStack));

}

Page 27: Chapter 21 Generics

WildCardDemo1.max

27

/** Find the maximum in a stack of numbers */ public static double max(GenericStack<Number> stack) { /** intStack is an instance of GenericStack<Integer> but NOT GenericStack<Number> */ double max = stack.pop().doubleValue(); // initialize max

while (!stack.isEmpty()) { double value = stack.pop().doubleValue(); if (value > max) max = value; }

return max; }

Page 28: Chapter 21 Generics

28

/** <?> means any subtype of Object and associated with GenericStack */public class WildCardDemo2 { public static void main(String[] args ) { GenericStack<Integer> intStack = new GenericStack<Integer>(); intStack.push(1); // 1 is autoboxed into new Integer(1) intStack.push(2); intStack.push(-2);

print(intStack); System.out.println(); }

// Print objects and empties the stack public static void print(GenericStack<?> stack) {

/** 1st form: ^^^ unbounded wildcard, same as ? extends Object */ while (!stack.isEmpty()) { System.out.print(stack.pop() + " "); } }}

Page 29: Chapter 21 Generics

29

/** <?> means any subtype of Object and associated with GenericStack */public class WildCardDemo2A { public static void main(String[] args ) { GenericStack<Integer> intStack = new GenericStack<Integer>(); intStack.push(1); // 1 is autoboxed into new Integer(1) intStack.push(2); intStack.push(-2);

print(intStack); System.out.println(); }

// Print objects and empties the stack public static void print(GenericStack<? extends Number> stack) {

/** 2nd form: ^^^^^^^^^^^^^^^^^^ bounded wildcard, Number or subtype */ while (!stack.isEmpty()) { System.out.print(stack.pop() + " "); } }}

Page 30: Chapter 21 Generics

WildCardDemo3 <? super T>

30

/** <? super T> represents type T or supertype of T */public class WildCardDemo3 { public static void main(String[] args) { GenericStack<String> stack1 = new GenericStack<String>(); GenericStack<Object> stack2 = new GenericStack<Object>(); stack2.push("Java"); stack2.push(2); stack1.push("Sun");

add(stack1, stack2); WildCardDemo2.print(stack2); System.out.println(); }

Page 31: Chapter 21 Generics

GenericStack<? super T>

31

/** Pop each element of stack1 and push it on stack2 */ public static <T> void add( GenericStack<T> stack1, GenericStack<? super T> stack2) {/** 3rd form ^^^^^^^^^^^ type T or super type of T. Here Object is super type of String will compile fine.*/ while (!stack1.isEmpty()) stack2.push(stack1.pop()); }}

Page 32: Chapter 21 Generics

Watch out What if we replace GenericStack<? super T> stack2) { in line 15 of GenericStack3 by GenericStack<T> stack2) { ? Reasoning: Only Strings are in stack1, but

String is subclass of Object. Must we declare stack2 as GenericStack<? super T> ?

32

Page 33: Chapter 21 Generics

Answer – NO!

Change the code in WildCardDemo3A and compile

<T>add( GenericStack<T>, GenericStack<T>) in WildCardDemo3A cannot be applied to (GenericStack<java.lang.String> stack1, GenericStack<java.lang.Object> stack2)

33

Page 34: Chapter 21 Generics

34

Generic Types and Wildcard Types

Object

?

? super E

E’s superclass

E

? extends E

E’s subclass

Object

A<?>

A<? super B>

A<B’s subclass>

A<? extends B>

A<B>

A<B’s superclass>

Page 35: Chapter 21 Generics

35

Erasure and Restrictions on Generics

Implementation of Generics - type erasure. - Compiler uses the generic type information to compile the code, but erases it afterwards. - Hence generic information is not available at run time. - Reason: To enable the generic code to be backward-compatible with the legacy code that uses raw types.

Page 36: Chapter 21 Generics

36

Compile Time Checking Example:-Compiler checks whether generics is used correctly for the code in (a);-Translates it into the equivalent code in (b) for runtime use. The code in (b) uses the raw type.

ArrayList<String> list = new ArrayList<String>(); list.add("Oklahoma"); String state = list.get(0);

(a) (b)

ArrayList list = new ArrayList(); list.add("Oklahoma"); String state = (String)(list.get(0));

Page 37: Chapter 21 Generics

37

Important Facts It is important to note that a generic class is shared by all its instances regardless of its actual generic type.

GenericStack<String> stack1 = new GenericStack<String>();GenericStack<Integer> stack2 = new GenericStack<Integer>();

Although GenericStack<String> and GenericStack<Integer> are two types, but there is only one class GenericStack loaded into the JVM.

Page 38: Chapter 21 Generics

38

Restrictions on Generics

Restriction 1: Cannot Create an Instance of a Generic Type. (i.e., new E()).

Restriction 2: Generic Array Creation is Not Allowed. (i.e., new E[100]).

Restriction 3: A Generic Type Parameter of a Class Is Not Allowed in a Static Context.

Restriction 4: Exception Classes Cannot be Generic.

Page 39: Chapter 21 Generics

Restriction 1

Restriction 1: Cannot Create an Instance of a Generic Type.

E Object = new E(); // wrong

Reason: new E(); is run at runtime but the generic type E is not available at runtime.

39

Page 40: Chapter 21 Generics

Restriction 2

Restriction 2: Generic Array Creation is Not Allowed.

E[] elements = new E[100]; // wrong There is no E class Circumvent: E[] elements = (E[]) new Object[100]; But warning is unavoidable

40

Page 41: Chapter 21 Generics

Restriction 2 example

41

ArrayList<String>[] list = new ArrayList<String>[10] //wrong

ArrayList<String>[] list = (ArrayList<String>[]) new ArrayList[10]; // to circumvent// But still compiler warning

Page 42: Chapter 21 Generics

Restriction 3

Restriction 3: A Generic Type Parameter of a Class Is Not Allowed in a Static Context.

Reason: All instance of a generic class have the same runtime class, static (class) variables and method are shared by all instances. Hence it is illegal to refer to a generic type parameter for a class in static method or field.

42

Page 43: Chapter 21 Generics

Restriction 3

public class Teste <E> { public static void m(E obj1) //illegal }

– public static E obj; // illegal

}

43

Page 44: Chapter 21 Generics

Restriction 4

Restriction 4: Exception Classes Cannot be Generic.

Reason: A generic class may not extend java.util.Throwable

44

Page 45: Chapter 21 Generics

Restriction 4

45

public class MyException<T> extends Exception { - - -

} // illegal

try {. . . }Catch (MyException<T> ex) {. . .} /* JVM would have to match the type in runtime but the type is not available at runtime. */

Page 46: Chapter 21 Generics

Now repeat TestArrayList

See BJ_TestArrayListNew

46