1 / 48

Generics

Generics. Introduction. In any nontrivial software project, bugs are simply a fact of life. Careful programming & testing can help reduce their pervasiveness, but somehow, somewhere, they'll always find a way to creep into your code. Fortunately, some bugs are easier to detect than others. .

ora
Télécharger la présentation

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. Generics M. Shoaib Farooq

  2. Introduction • In any nontrivial software project, bugs are simply a fact of life. • Careful programming & testing can help reduce their pervasiveness, but somehow, somewhere, they'll always find a way to creep into your code. • Fortunately, some bugs are easier to detect than others. M. Shoaib Farooq

  3. Compile-time bugs vs. Runtime bugs • Compile-time bugs, for example, tell you immediately that something is wrong; you can use the compiler's error messages to figure out what the problem is and fix it, right then and there. • Runtime bugs, however, can be much more problematic; they don't always surface immediately. Generics add stability to your code by making more of your bugs detectable at compile time. M. Shoaib Farooq

  4. What are Java generics • JDK 1.5 introduces several extensions to the Java programming language. One of these is the introduction of generics. • Java Generics are a language feature that allows for definition and use of generic types and methods. • Generics are classes or interfaces that can be instantiated with a variety of types. • They have 1 or more formal type parameters • Using a generic you specify an actual type M. Shoaib Farooq

  5. What are Java generics • Generic types or methods differ from regular types and methods in that they have type parameters. • Examples of generic types can be found in the collection framework of the J2SE 5.0 platform libraries. M. Shoaib Farooq

  6. Example • A class like LinkedList<E> is a generic type. • It has a type parameter E that represents the type of the elements stored in the list. • We can use a LinkedList<String> or a LinkedList<Integer>, thereby specifying that we mean a list of strings or integral values respectively. M. Shoaib Farooq

  7. Type Parameter : “A place holder for a type argument” • Type Argument: “Type that replace the formal type parameters” LinkedList <String > list = new LinkedList<String>(); LinkedList <Integer > list = new LinkedList<Integer>(); Instantiations, such as LinkedList<String> or a LinkedList<Integer>,are called parameterized types, and String and Integer are the respective actual type arguments. M. Shoaib Farooq

  8. Usage of Non Generic Collection • Prior to the JDK 5.0 release, when you created a Collection, you could put any object in it. Vector myVector= new Vector(); myVector.addElement(new Integer(10)); myVector.addElement ("Hello, World"); • Getting items out of the collection required you to use a casting operation: Integer myInt = (Integer) myVector.elementAt(0); String myString = (String) myVector.elementAt(1); M. Shoaib Farooq

  9. Usage of Non Generic Collection • If you accidentally cast the wrong type, the program would successfully compile, but an exception would be thrown at runtime. Vector myVector= new Vector(); myVector.addElement(new Integer(10)); …….// other code Integer myInt = (Integer) myVector.elementAt(0); String myString = (String) myVector.elementAt(0); Compiles Safely but FAILS at Runtime Cast Required M. Shoaib Farooq

  10. Generics • J2SE 5.0 provides compile-time type safety with the Java Collections framework through generics • Generics allows you to specify, at compile-time, the types of objects you want to store in a Collection. Then when you add and get items from the list, the list already knows what types of objects are supposed to be acted on. • So you don't need to cast anything. The "<>" characters are used to designate what type is to be stored. If the wrong type of data is provided, a compile-time exception is thrown. M. Shoaib Farooq

  11. Generics (cont’d) • Example: import java.util.*; public class First { public static void main(String args[]) { List<Integer> myList = new ArrayList<Integer>(10); myList.add(10); // OK myList.add("Hello, World"); // OK ??? } } M. Shoaib Farooq

  12. Generics (cont’d) • Example (compile-time exception): import java.util.*; public class First { public static void main(String args[]) { List<Integer> myList = new ArrayList<Integer>(10); myList.add(10); //  Autoboxing converted the int type to an Integer myList.add("Hello, World"); } } First.java:7: cannot find symbol symbol : method add(java.lang.String) location: interface java.util.List<java.lang.Integer> myList.add("Hello, World"); ^ 1 error M. Shoaib Farooq

  13. Benefits of generics • Making code better • Runtime: No ClassCastException • Compile time: Compiler discovers wrong uses of types. • Making code more flexible • Generic classes can be instantiated with different types. M. Shoaib Farooq

  14. Type Safety In Java, a program is considered type-safe if it • compiles without errors and warnings • does not raise any unexpected ClassCastException at runtime. • Using a parameterized type such as LinkedList<String>, instead of LinkedList, enables the compiler to perform more type checks and requires fewer dynamic casts. • This way errors are detected earlier, in the sense that they are reported at compile-time by means of a compiler error message rather than at runtime by means of an exception. M. Shoaib Farooq

  15. Consider the example of a LinkedList<String>. The type LinkedList<String> expresses that the list is a homogenous list of elements of type String. • Based on the stronger information the compiler performs type checks in order to ensure that a LinkedList<String> contains only strings as elements. • Any attempt to add an alien element is rejected with a compiler error message. M. Shoaib Farooq

  16. Example (using a parameterized type): LinkedList<String> list = new LinkedList<String>(); list.add("abc"); // fine list.add(new Date()); // error M. Shoaib Farooq

  17. Example (using a non-parameterized type): LinkedListlist = new LinkedList(); list.add("abc"); // fine list.add(new Date()); // fine as well • A non-parameterized list is a sequence of elements of type Object. M. Shoaib Farooq

  18. Example (using a parameterized type): • Since it is ensured that a LinkedList<String> contains strings it is not necessary to cast an element retrieved from the list to type String. LinkedList<String> list = new LinkedList<String>(); list.add("abc"); String s = list.get(0); // no cast needed M. Shoaib Farooq

  19. Same example (using a non-parameterized type): • Using a plain LinkedList, there is no knowledge and no guarantee regarding the type of the element retrieved. • All retrieval methods return an Object reference, which must be cast down to the actual type of the element retrieved. • LinkedList list = new LinkedList(); • list.add("abc"); • String s = (String)list.get(0); // cast required M. Shoaib Farooq

  20. definition of a generic type • definition of a generic method • type parameters • type parameter bounds • type arguments • wildcards • wildcard bounds • instantiation of a generic type • raw type • concrete instantiation • wildcard instantiation • instantiation of a generic method • automatic type inference • explicit type argument specification M. Shoaib Farooq

  21. How to define a generic type? • Like a regular type, but with a type parameter declaration attached. • A generic type is a reference type that has one or more type parameters. • In the definition of the generic type, the type parameter section follows the type name. • It is a comma separated list of identifiers and is delimited by angle brackets. M. Shoaib Farooq

  22. Example (of a generic type): class Pair<X,Y> { private X first; private Y second; public Pair(X a1, Y a2) { first = a1; second = a2; } public static <X,Y>void printPair(Pair<X,Y> pair) { System.out.println("("+pair.getFirst()+","+pair.getSecond()+")"); } public X getFirst() { return first; } public Y getSecond() { return second; } public void setFirst(X arg) { first = arg; } public void setSecond(Y arg) { second = arg; } } M. Shoaib Farooq

  23. Instantiation of Generic Type public static void main(String o[]){ Pair<String,Long> limit1 = new Pair<String,Long>("maximum",124L); Pair<String,Date> limit2 = new Pair<String,Date>("Current Date",new Date()); Pair.printPair(limit1); Pair.printPair(limit2);} SEE Stack.java CONCRETE INSTANTIATIONS M. Shoaib Farooq

  24. A Primitive Type Cannot be Plugged in for a Type Parameter!!! • The type plugged in for a type parameter must always be a reference type: • It cannot be a primitive type such as int, double, or char • However, now that Java has automatic boxing, this is not a big restriction. M. Shoaib Farooq

  25. Bounded Type Parameters • There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. • For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. • This is what bounded type parameters are for. M. Shoaib Farooq

  26. Bounded Type Parameters • To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound, which in this example is Number. Note that, in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces). M. Shoaib Farooq

  27. Generic Methods “A method with type parameters” • Not only types can be generic, but methods can be generic, too. • Static and non-static methods as well as constructors can have type parameters. • The syntax for declaration of the formal type parameters is similar to the syntax for generic types. • The type parameter section is delimited by angle brackets and appears before the method's return type. Its syntax and meaning is identical to the type parameter list of a generic type. M. Shoaib Farooq

  28. class Collections { public static <A extends Comparable<A>> A max (Collection<A> xs) { Iterator<A> xi = xs.iterator(); A w = xi.next(); while (xi.hasNext()) { A x = xi.next(); if (w.compareTo(x) < 0) w = x; } return w; } } • The max method has one type parameter, named A. It is a place holder for the element type of the collection that the method works on. The type parameter has a bound; it must be a type that is a subtype of Comparable<A>. M. Shoaib Farooq

  29. Generic Methods static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) { c.add(o); // correct } } • See M. Shoaib Farooq

  30. Subtyping It's possible to assign an object of one type to an object of another type provided that the types are compatible. For example, you can assign an Integer to an Object, since Object is one of Integer's supertypes: Object someObject = new Object(); Integer someInteger = new Integer(10); someObject = someInteger; // OK In object-oriented terminology, this is called an "is a" relationship. Since an Integer is a kind of Object, the assignment is allowed M. Shoaib Farooq

  31. Subtyping But Integer is also a kind of Number, so the following code is valid as well: public void someMethod(Number n){ // method body omitted } someMethod(new Integer(10)); // OK someMethod(new Double(10.1)); // OK M. Shoaib Farooq

  32. Subtyping • The same is also true with generics. You can perform a generic type invocation, passing Number as its type argument, and any subsequent invocation of add will be allowed if the argument is compatible with Number: Vector<Number> vector = new Vector<Number>(); vector.addElement(new Integer(10)); // OK vector.addElement(new Double(10.1)); // OK M. Shoaib Farooq

  33. Subtyping void printAll(Vector<Object> c) { for (Object o : c) System.out.println(o); } Vector<String> list = new Vector<String>(); ... fill list ... printAll(list); // error M. Shoaib Farooq

  34. Subtyping Is Vector<Object> a supertype of Vector<String>?  No, different instantiations of the same generic type for different concrete type arguments have no type relationship. M. Shoaib Farooq

  35. Subtyping • In general, if Foo is a subtype (subclass or subinterface) of Bar, and G is some generic type declaration, it is not the case that G<Foo> is a subtype of G<Bar>. M. Shoaib Farooq

  36. Wildcard parameterized type • They do not have concrete types as type arguments, but so-called wildcards. • A wildcard is a syntactic construct with a"?" that denotes not just one type, but a family of types. In its simplest form a wildcard is just a question mark and stands for "all types". • A wildcard describes a family of types. There are 3 different flavors of wildcards: • "?" - the unbounded wildcard. It stands for the family of all types. • "? extends Type " - a wildcard with an upper bound. It stands for the family of all types that are subtypes of Type, type Type being included. • "? super Type " - a wildcard with a lower bound. It stands for the family of all types that are super types of Type, type Type being included. M. Shoaib Farooq

  37. WildCards • Consider the problem of writing a routine that prints out all the elements in a collection. Here’s how you might write it in an older version of the language: void printCollection(Collection c) { Iteratori = c.iterator(); for (k = 0; k < c.size(); k++) { System.out.println(i.next()); }} M. Shoaib Farooq

  38. WildCards And here is a naive attempt at writing it using generics (and the new for loop syntax): void printCollection(Collection<Object> c) { for (Object e : c) { System.out.println(e); }} M. Shoaib Farooq

  39. WildCards • The problem is that this new version is much less useful than the old one. • Whereas the old code could be called with any kind of collection as a parameter, the new code only takes collection<Object>, which, as we’ve just demonstrated, is not a supertype of all kinds of collections! So what is the supertype of all kinds of collections? • Its written Collection<?> (pronounced “collection of unknown”), that is, a collection whose element type matches anything. It’s called a wildcard type for obvious reasons. M. Shoaib Farooq

  40. WildCards We can write: void printCollection(Collection<?> c) { for (Object e : c) { System.out.println(e); } } Now, we can call it with any type of collection. Notice that inside printCollection(), we can still read elements from c and give them type Object. M. Shoaib Farooq

  41. Type Erasure • When a generic type is instantiated, the compiler translates those types by a technique called type erasure “ a process where the compiler removes all information related to type parameters and type arguments within a class or method” • Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics. M. Shoaib Farooq

  42. Type Erasure public class MyClass<E> { public static void myMethod(Object item) { if (item instanceof E) { //Compiler error ... } E item2 = new E(); //Compiler error E[] iArray = new E[10]; //Compiler error E obj = (E)new Object(); //Unchecked cast warning } } M. Shoaib Farooq

  43. Type Erasure • The operations shown in bold are meaningless at runtime because the compiler removes all information about the actual type argument (represented by the type parameter E) at compile time. M. Shoaib Farooq

  44. Type Erasure • Type erasure exists so that new code may continue to interface with legacy code. Using a raw type for any other reason is considered bad programming practice and should be avoided whenever possible. • When mixing legacy code with generic code, you may encounter warning messages similar to the following: Note: WarningDemo.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. M. Shoaib Farooq

  45. Warning Demo class Box<T> { private T t; // T stands for "Type" public void add(T t) { this.t = t; } public T get() { return t; } } M. Shoaib Farooq

  46. WarningDemo public class WarningDemo { public static void main(String[] args){ Box<Integer> bi; bi = createBox(); } static Box createBox(){ return new Box(); } M. Shoaib Farooq

  47. WarningDemo Recompiling with -Xlint: unchecked reveals the following additional information: WarningDemo.java:4: warning: [unchecked] unchecked conversion found : Box required: Box<java.lang.Integer> bi = createBox(); ^ 1 warning M. Shoaib Farooq

  48. Why do instantiations of a generic type share the same runtime type? Because of type erasure • The compiler translates generic and parameterized types by a technique called type erasure. • Basically, it elides all information related to type parameters and type arguments. For instance, the parameterized type List<String> is translated to type List, which is the so-called raw type. • The same happens for the parameterized type List<Long>; it also appears as List in the bytecode. • After translation by type erasure, all information regarding type parameters and type arguments has disappeared. As a result, all instantiations of the same generic type share the same runtime type, namely the raw type. M. Shoaib Farooq

More Related