1 / 46

Chapter 21 Generics

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).

gallia
Download Presentation

Chapter 21 Generics

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 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).

  3. Example: Pre_Java5

  4. See these warnings before? Warnings from last compilations <program> uses unchecked or unsafe operations Recompile with –Xlint unchecked for details

  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.

  6. ArrayList public ArrayList() Constructs an empty list with an initial capacity of ten. add public 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))

  7. Generic Type Generic Instantiation Runtime error Restricts to type Date Improves reliability Compile error

  8. Generic ArrayList in JDK 1.5

  9. Fix the Warning in BJ_Java5 import 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.

  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

  11. Declaring Generic Classes and Interfaces BJ_GenericStack

  12. To print elements of different types Before Java5 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) { // . . . } }

  13. To print elements of different types From Java5 with Generic Methods 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(); } }

  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(); }

  15. Can I specify the type as say <F>? 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(); } }

  16. Can I specify subtypes? Suppose we want to restrict to Circle and Rectangle objects only in class BoundedTypeDemo

  17. Bounded Generic Type public 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 GeometricObject public static <E extends GeometricObject> boolean equalArea(E object1, E object2) { return object1.findArea() == object2.findArea(); }

  18. Bounded Generic Type • See BJ_BoundedType

  19. Raw Type and Backward Compatibility // raw type GenericStack stack = new GenericStack(); This is roughly equivalent to GenericStack<Object> stack = new GenericStack<Object>();

  20. Raw Type: Compile? Run? Safe? Why? // Max.java: Find a maximum object public 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 Max.max("Welcome", 23); public static void main(String[] args) { System.out.println("max is " + Max.max("Welcome", 23)); } }

  21. Runtime Exception on running class Max: 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)

  22. Make it Safe – See class BJ_Max1 // Max1.java: Find a maximum object public 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; } } Max.max("Welcome", 23);

  23. Compilation error instead

  24. Wildcards Why wildcards are necessary? See this example. WildCardDemo1 ? unbounded wildcard ? Extends T bounded wildcard ? Super T lower bound wildcard: WildCardDemo2 WildCardDemo3

  25. WildCardDemo1 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)); }

  26. WildCardDemo1.max /** 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; }

  27. /** <?> 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() + " "); } } }

  28. /** <?> 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() + " "); } } }

  29. WildCardDemo3 <? super T> /** <? 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(); }

  30. GenericStack<? super T> /** 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()); } }

  31. 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. 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. Generic Types and Wildcard Types

  34. 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.

  35. 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.

  36. 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.

  37. 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.

  38. 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. 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. Restriction 2 example ArrayList<String>[] list = new ArrayList<String>[10] //wrong ArrayList<String>[] list = (ArrayList<String>[]) new ArrayList[10]; // to circumvent // But still compiler warning

  41. 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. Restriction 3 • public class Teste <E> { • public static void m(E obj1) //illegal • } • public static E obj; // illegal }

  43. Restriction 4 • Restriction 4: Exception Classes Cannot be Generic. • Reason: A generic class may not extend java.util.Throwable

  44. Restriction 4 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. */

  45. Now repeat TestArrayList • See BJ_TestArrayListNew

More Related