Your SlideShare is downloading. ×
Java Generics Introduction - Syntax Advantages and Pitfalls
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Java Generics Introduction - Syntax Advantages and Pitfalls

3,910
views

Published on

This is the best introduction presentation for Java Generics I have seen ever.

This is the best introduction presentation for Java Generics I have seen ever.

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
3,910
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
90
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Java Generics Barney Marispini 08.31.05 1
  • 2. Topics• What Are Generics?• The Collections Framework• Points of Interest• Type Erasure• Type Parameters• Bounded Types• Generic Methods And Constructors• Generic Classes And Interfaces• Legacy Conversion• Generics In Context• Summary• Resources• Discussion 2
  • 3. What Are Generics? 3
  • 4. Generic History 101• Generics represent the most significant change to the Java language since the 1.0 release.• Over five years in the making, JSR 14 (Generics) was one of the first Java Specification Requests.• Generics are desirable because they let you write code that is safer and easier to read than code that is littered with Object variables and casts.• Generic programming is now achieved via type parameters as opposed to inheritance. 4
  • 5. Life Before Generics• Generalized classes, interfaces, and methods were accomplished by operating through references of type Object. public Object get(int index);• Explicit casting was required in order to downcast Object to whatever concrete implementation was being represented. String value = (String) list.get(0);• Runtime exceptions ran rampant because type safety could not be guaranteed by the compiler. 5
  • 6. The Generic New World Order• Generics means parameterized types. – The type upon which a generic method, class, or interface operates is specified as a parameter.• Generics make it possible to create a single class, for example, that automatically works with different types of data (Strings, Integers...).• Type safety is now ensured by the compiler. – All casts are automatic and implicit.• Generics expand the ability to write reusable code and do so in a safe, easy, and inviting manner. 6
  • 7. Raw Type vs. Generics Example• Raw type version List list = new ArrayList(); list.add("1"); String value = (String) list.get(0);• Generics version List<String> list = new ArrayList<String>(); list.add("1"); String value = list.get(0);Note: The term “raw” refers to a generic type used without actual type arguments. List is the raw type of List<E>. 7
  • 8. Example Continued...• Raw type version List list = new ArrayList(); list.add("1"); // Compiler permits list.add(new Integer(1)); // ClassCastException String value = (String) list.get(1);• Generics version List<String> list = new ArrayList<String>(); list.add("1"); // Compilation error list.add(new Integer(1)); String value = list.get(1); 8
  • 9. The Collections Framework 9
  • 10. The Collections Framework• The entire collections framework has been reworked using generics.• Raw types provide a means of backward compatibility (syntactic sugar). – Under the hood, when a raw type is used, the compiler actually substitutes the upper bound of each variable (typically Object) as the actual type argument for that variable. The following are equivalent… List list = new ArrayList(); // Raw Type List<Object> list = new ArrayList<Object>(); 10
  • 11. The New & Improved List Interfacepublic interface List<E> extends Collection<E> { boolean add(E o); E get(int index); Iterator<E> iterator();}• E is a type variable or placeholder. It will be replaced by the actual reference type passed as an argument to the generic class. 11
  • 12. List Interface Continued...public interface List<String> extends Collection<String> { boolean add(String o); String get(int index); Iterator<String> iterator();}• The type argument, String, replaces all occurrences of E at runtime. // String is passed as the parameterized type List<String> list = new ArrayList<String>(); 12
  • 13. Points of Interest 13
  • 14. Generic Points of Interest• The compiler generates only one class. – All invocations share the same generic type.• Only object reference types can be passed as type parameters. – Primitive types cannot be passed as type parameters.• Generic type parameters are just like ordinary method parameters. When invoked, the passed type arguments (String) replace the actual type parameters (E). 14
  • 15. Points of Interest Continued...• A reference of one specific version of a generic type cannot be assigned to a different version of the same same generic type. // Wrong! (Same generic, different versions) listOfStrings = listOfIntegers; // Wrong! (This one’s tricky. Even though String // subclasses Object, we can’t be sure listOfObjects // is only holding Strings) listOfObjects = listOfStrings;• Generics are only implemented in the compiler. – No generic type information is available at runtime due to erasure. 15
  • 16. Type Erasure 16
  • 17. The Concept of Erasure• To ensure backward compatibility, a process called type erasure is used to map the new syntax to the current JVM specification.• Type erasure is the process of translating or rewriting code that uses generics into non- generic code.• When generics are compiled, all generic-specific information is completely erased. 17
  • 18. Erasure Continued...• During erasure, all type variables are replaced by their upper bound or Object if not specified. // The erasure of T is Number <T extends Number> // The erasure of T is Object <T>• The compiler adds casts, type conversions, and synthetic bridge methods as necessary to ensure type-correct code. – Bridge methods are inserted into subtypes of parameterized supertypes to ensure that subtyping works as expected. 18
  • 19. Erasure Example...// Pre-Erasure (Notice the type variables)public void method() { List<String> list = new ArrayList<String>(); list.add("value"); print(list);}// Pre-Erasure (Notice the type variables and omitted cast)public void print(Collection<String> collection) { Iterator<String> it = collection.iterator(); while (it.hasNext()) { String element = it.next(); System.out.println(element); }} 19
  • 20. Example Continued...// Post-Erasure (Erased generics)public void method() { List list = new ArrayList(); list.add("value"); print(list);}// Post-Erasure (Erased generics and inserted cast)public void print(Collection collection) { String s; for (Iterator it = collection.iterator(); it.hasNext();) { s = (String) iterator.next(); System.out.println(s); }} 20
  • 21. Type Parameters 21
  • 22. Multiple Type Parameters• A generic type can accept more than one type variable. For example, the Map interface accepts two variables. The first (K) defines the key type and the second (V) defines the value type. public interface Map<K,V> { V put(K key, V value); V get(Object key); } Map<String, String> map = new HashMap<String, String>(); map.put("key", "value"); String value = map.get("key"); 22
  • 23. Passing Generics To Generics• A generic type is itself a type that can be passed to another generic. Below is how you would create a list that holds a list of Strings. List<String> listOfStrings = new ArrayList<String>(); listOfStrings.add("value"); List<List<String>> listOfLists = new ArrayList<List<String>>(); listOfLists.add(listOfStrings); String value = listOfLists.get(0).get(0); 23
  • 24. Wildcard Arguments• Wildcards are used to signify an unknown type.• Syntactically, wildcards are specified with <?>. // List<?> is the pseudo-supertype of all lists // It contains a list of unknown types public void printList(List<?> list) { // Type variables are always Objects for (Object element : list) { System.out.println(element); } } Question: What is the difference between List<?> and List<Object>? What would happen if we replaced the wildcard with Object? 24
  • 25. Wildcards Continued...• Wildcard parameterized types are similar to interfaces... – They can be declared, but no objects of a wildcard parameterized type can be created. // Invalid instantiation attempt of a wildcard List<?> list = new ArrayList<?>(); – They can refer to an Object that is of a type that belongs to a family of types the wildcard denotes. // Valid because Long extends Number (same family) List<? extends Number> list = new ArrayList<Long>(); // Wrong, String does not extend Number (not related) List<? extends Number> list = new ArrayList<String>; 25
  • 26. Bounded Types 26
  • 27. Bounded Types• Used to restrict what can be passed to a generic by defining an upper or lower bound of a type variable.• Both upper and lower bounds are inclusive.• Bounds can be either a class or interface. // The upper bound is an interface List<? extends Serializable> // The lower bound is a class List<? super Integer> 27
  • 28. Upper Bounds• Upper bounds are defined as follows… <? extends superclass>• The extends keyword was chosen because it is a reasonable approximation of the subtype concept, and the Java designers didn’t want to add a new keyword to the language.• The following accepts a Shape or any subclass of Shape such as Circle or Square. // Shape is the upper bound List<? extends Shape> 28
  • 29. Lower Bounds• While not as useful, it is also possible to define the lower bound of a type variable, by using the super keyword. <? super subclass>• The following will take a list of JDialogs or any object whose class is a superclass of JDialog such as Dialog or Window. // JDialog is the lower bound List<? super JDialog> 29
  • 30. Multiple Bounds• Type variables can also have multiple bounds.• Use ampersands to separate bounded types. <expression... class & interface & interface...>• As with Java inheritance, there can be multiple interfaces, but only one class, and it must be the first bound specified in the list of bounded types. // Number is the only class and is listed first. // The interfaces are randomly ordered. // Notice that T is passed to Comparable<T>. <T extends Number & Comparable<T> & Serializable> 30
  • 31. Generic Methods And Constructors 31
  • 32. Generic Methods• Methods with type parameters are referred to as generic methods.• They can exist within both generic classes and non-generic classes.• The scope of a method’s type parameter is restricted to the method itself.• Use when dependencies exist among the types of one or more arguments and/or return type. // The argument and return type are both of type T public <T> T[] toArray(T[] a) 32
  • 33. Generic Methods Continued...• Insert type variables between the modifiers and return type. modifiers <typeVariables> returnType methodName(...)• When calling a generic method, place the type arguments before the method name. objectReference.<typeVariables>methodName();Note: In most cases, you can omit the type parameters from the method call because the compiler will typically be able to discern which method based on the actual type arguments. 33
  • 34. Generic Methods Continued...public class Collections { public static <T> void copy( List<? super T> dest, List<? extends T> src) { ... }}• T is a type variable or placeholder. It will be replaced by the actual reference type passed as an argument to the generic method. Collections.<Dialog>copy(windowList, jDialogList); Collections.copy(windowList, jDialogList); 34
  • 35. Generic Constructors• Constructors with type parameters are referred to as generic constructors .• They can exist within both generic classes and non-generic classes.• The scope of a constructor’s type parameter is restricted to the constructor itself.• Use when dependencies exist among the types of one or more arguments.• Just as with generic methods, type parameters of generic constructors need not be provided explicitly when invoked. 35
  • 36. Generic Classes And Interfaces 36
  • 37. Custom Generic Classes• Generic classes use the following syntax… class className<typeParameters> { ... }• Below is the syntax for declaring a reference to a generic class. className<typeArguments> variableName = new className<typeArguments>(constructorArguments);Note: See GenericExample class. 37
  • 38. Generic Interfaces• As demonstrated earlier with List and Map, interfaces can also be generic. public interface List<E> extends Collection<E> { boolean addAll(int index, Collection<? extends E> c); ListIterator<E> listIterator(int index); E set(int index, E element); }• The syntax is the same as with classes… interface interfaceName<typeParameters> { ... } 38
  • 39. Generic Class Hierarchies• The only difference between generic and non- generic hierarchies is that generic hierarchies require type variables be passed up the inheritance tree accordingly.• There are a few simple rules… – Generic classes can subclass other generic classes and non-generic classes. – Non-generic classes cannot subclass generic classes. • The reason is that a non-generic subclass cannot receive type parameters and therefore cannot pass anything to its generic superclass. – Subclasses are free to add their own parameters not required by the generic superclass. 39
  • 40. Generic Restrictions• Type parameters cannot be instantiated. // Wrong! (Can’t create an instance of T) objectReference = new T();• Static members cannot use a type parameter declared by the enclosing class. – However, you can declare static generic methods that define their own type parameters.• A generic class cannot extend Throwable. This means that you cannot create generic exception classes. 40
  • 41. Restrictions Continued...• It is not possible to instantiate an array whose base type is a type parameter. – The reason is that T does not exist at runtime, so there is no way for the compiler to know what type of array to actually create.public class Generic<T extends Number> { T[] array; Generic(T[] numbers) { array = new T[10]; // Can’t create an array of T array = numbers; // Reference assignments are fine }} 41
  • 42. Restrictions Continued...• It is also not possible to create an array of type- specific generic references. – Arrays of specific generic types simply aren’t allowed because they can lead to a loss of type safety. // Wrong! (Type-specific generic references) Generic<Integer>[] array = new Generic<Integer>[10]; // Okay! (Wildcards are acceptable) Generic<?>[] array = new Generic<?>[10]; 42
  • 43. Legacy Conversion 43
  • 44. Converting Legacy To Generics• Make certain that the generic API is not unduly restrictive; it must continue to support the original contract of the API.• You also need to ensure that the revised API retains binary compatibility with old clients. This implies that the erasure of the API must be the same as the original, ungenerified API. In most cases, this falls out naturally, but there are some subtle cases. 44
  • 45. Generics In Context 45
  • 46. Generics In Context• Because generics are such a fundamental change to the language, it’s important to have a solid understanding of them.• Most interaction with generics will happen as a result of using the collections framework.• For the most part, application developers won’t write a lot of custom generics, but will use the generics provided by various frameworks.• The heavy writing of custom generics seems to be most applicable for framework development. 46
  • 47. Drawbacks Of Generics• Steep learning curve – Generics are a fundamental change and require a completely different mindset. – Conceptually, generics can be difficult to grasp and can lead to code that is difficult to read and follow.• Added complexity – Many left C++ because of it’s complexity, some would argue that Java is headed down that same road. – Much of Java’s original appeal was its simplicity. Some believe that the trade-off for type safety is not worth the added complexity introduced by generics. 47
  • 48. Summary 48
  • 49. Summary• Generics are a powerful extension to the Java language because they streamline the creation of type-safe, reusable code.• Within generics, automatic casting and type converting are provided by the compiler.• The Collections framework has been entirely reworked. – Now collections can be restricted and guaranteed to only hold the specified type, passed as a parameter. – The need for type casting when retrieving an element from a collection has been entirely eliminated. 49
  • 50. Summary Continued...• Generics provide backward compatibility by enabling generic types to be used without type variables (raw types). – It is strongly recommended; however, that new applications avoid using raw types as future releases of Java may not support them (according to the Java Language Specification). 50
  • 51. Resources 51
  • 52. Additional Resources• Tutorials – http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf – http://www.onjava.com/pub/a/onjava/2005/07/06/generics.html – http://www.informit.com/articles/article.asp?p=170176&seqNum=1• Links – http://www.langer.camelot.de/GenericsFAQ/JavaGenericsFAQ.html – http://jcp.org/aboutJava/communityprocess/review/jsr014/ – http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html• Books – Java 2 v5.0 (Tiger) New Features – Java 5.0 Tiger: A Developers Notebook 52
  • 53. Discussion 53
  • 54. Open Discussion• Questions?• Comments?• Donations? 54