cpsc 331 data structures algorithms and their analysis
play

CPSC 331: Data Structures, Algorithms, and their Analysis - PowerPoint PPT Presentation

CPSC 331: Data Structures, Algorithms, and their Analysis Introduction to Java Generics Usman R. Alim Department of Computer Science Generics in Java Often times, we want to perform the same operations on various different types of data.


  1. CPSC 331: Data Structures, Algorithms, and their Analysis Introduction to Java Generics Usman R. Alim Department of Computer Science

  2. Generics in Java Often times, we want to perform the same operations on various different types of data. Rather than repeating the code for different types, it would be nice to have the same code work for all types. (e.g. a sort function that works on integers, doubles as well as strings.) Introduced in JDK 5, generics provide us with a way of accomplishing this. You have probably already used them without even realizing it. There are generics methods , classes and interfaces .

  3. Pair Example: Without Generics Consider a class that holds a pair of values of any type. Prior to Java 5, we’d do something like: public class Pair { Object x; Object y; public Pair( Object x, Object y ) { this.x = x; this.y = y; } public Object getX () { return x; } public Object getY () { return y; } // ... }

  4. Pair Example: Without Generics We can use this class to hold e.g. a pair of integers, or a pair of doubles. Pair pair1 = new Pair(new Integer (1), new Integer (2)); Pair pair2 = new Pair(new Double (1.) , new Double (2.));

  5. Pair Example: Without Generics We can use this class to hold e.g. a pair of integers, or a pair of doubles. Pair pair1 = new Pair(new Integer (1), new Integer (2)); Pair pair2 = new Pair(new Double (1.) , new Double (2.)); However, in order to retrieve an object, an explicit cast is needed. int k = (Integer)pair1.getX (); double d = (Double)pair2.getY ();

  6. Pair Example: Without Generics We can use this class to hold e.g. a pair of integers, or a pair of doubles. Pair pair1 = new Pair(new Integer (1), new Integer (2)); Pair pair2 = new Pair(new Double (1.) , new Double (2.)); However, in order to retrieve an object, an explicit cast is needed. int k = (Integer)pair1.getX (); double d = (Double)pair2.getY (); This is inconvenient and also leads to type safety issues. E.g. the following statements don’t signal any compile-time errors but will give runtime errors. int k = (Integer)pair2.getX (); // error double d = (Double)pair1.getY (); // error

  7. Pair Example: With Generics Generic classes allow us to write classes with parametrized types . Our pair example now looks like: public class Pair <T1 , T2 > { T1 x; // x is of type T1 T2 y; // y is of type T2 public Pair( T1 x, T2 y ) { this.x = x; this.y = y; } public T1 getX () { return x; } public T2 getY () { return y; } // ... } Here, T1 and T2 are type parameters.

  8. Pair Example: With Generics A pair of integers can now be created as follows: Pair <Integer , Integer > pair1 = new Pair <Integer , Integer > (new Integer (1), new Integer (2));

  9. Pair Example: With Generics A pair of integers can now be created as follows: Pair <Integer , Integer > pair1 = new Pair <Integer , Integer > (new Integer (1), new Integer (2)); Arguments of the second diamond operator ( <> ) can be omitted, and we can use autoboxing e.g. Pair <Integer , Integer > pair1 = new Pair <>(1, 2);

  10. Pair Example: With Generics A pair of integers can now be created as follows: Pair <Integer , Integer > pair1 = new Pair <Integer , Integer > (new Integer (1), new Integer (2)); Arguments of the second diamond operator ( <> ) can be omitted, and we can use autoboxing e.g. Pair <Integer , Integer > pair1 = new Pair <>(1, 2); Casts are no longer necessary, incompatible type assignments are checked at compile time, e.g. Double d1 = pair1.getX (); // not allowed double d2 = pair1.getX (); // ok due to unboxing

  11. Extending Generic Classes Generic classes can be extended to non-generic or generic classes.

  12. Extending Generic Classes Generic classes can be extended to non-generic or generic classes. Let’s extend the Pair class to a Point class: public class Point extends Pair <Double , Double > { public Point(Double x, Double y) { super(x,y); } public double getLength2 () { return getX ()* getX () + getY ()* getY (); } }

  13. Extending Generic Classes Generic classes can be extended to non-generic or generic classes. Let’s extend the Pair class to a Point class: public class Point extends Pair <Double , Double > { public Point(Double x, Double y) { super(x,y); } public double getLength2 () { return getX ()* getX () + getY ()* getY (); } } Point is a non-generic class: Point p = new Point( new Double (1.) , new Double (2.)); System.out.println( p.getLength2 () );

  14. Extending Generic Classes Let’s extend the Pair class to a generic Triple class that has only one type parameter. public class Triple <T> extends Pair <T, T> { T z; // add another member public Triple(T x, T y, T z) { super(x,y); this.z = z; } public T getZ () { return z; } }

  15. Extending Generic Classes Let’s extend the Pair class to a generic Triple class that has only one type parameter. public class Triple <T> extends Pair <T, T> { T z; // add another member public Triple(T x, T y, T z) { super(x,y); this.z = z; } public T getZ () { return z; } } Triple is a generic class: Triple <Integer > tr = new Triple <> (new Integer (1), new Integer (2), new Integer (3)); System.out.println( tr.getZ () );

  16. Generics and Subtyping If B is a subtype of A and G is a generic type, it is not the case that G<B> is a subtype of G<A> .

  17. Generics and Subtyping If B is a subtype of A and G is a generic type, it is not the case that G<B> is a subtype of G<A> . For example, a Triple<Integer> is-a Pair<Integer, Integer> : Triple <Integer > tr = new Triple <> (new Integer (1), new Integer (2), new Integer (3)); Pair <Integer , Integer > pr = tr; // ok

  18. Generics and Subtyping If B is a subtype of A and G is a generic type, it is not the case that G<B> is a subtype of G<A> . For example, a Triple<Integer> is-a Pair<Integer, Integer> : Triple <Integer > tr = new Triple <> (new Integer (1), new Integer (2), new Integer (3)); Pair <Integer , Integer > pr = tr; // ok However, a Triple<Integer> is not a Triple<Object> even though an Integer is-an Object : Triple <Integer > tr = new Triple <> (new Integer (1), new Integer (2), new Integer (3)); Triple <Object > tro = tr; // error!

  19. Wildcards The previous example raises an interesting question, is there a generic type that can be used as a supertype? Yes, Java has wildcard types.

  20. Wildcards The previous example raises an interesting question, is there a generic type that can be used as a supertype? Yes, Java has wildcard types. The type Triple<?> is a wildcard type that can be used to refer to any kind of Triple . For example the method void printTriple( Triple <?> tr ) { System.out.println( "" + tr.getX () + ’\n’ + tr.getY () + ’\n’ + tr.getZ () ); } can be used to print out any kind of triple.

  21. Wildcards The previous example raises an interesting question, is there a generic type that can be used as a supertype? Yes, Java has wildcard types. The type Triple<?> is a wildcard type that can be used to refer to any kind of Triple . For example the method void printTriple( Triple <?> tr ) { System.out.println( "" + tr.getX () + ’\n’ + tr.getY () + ’\n’ + tr.getZ () ); } can be used to print out any kind of triple. Wildcards can also be used to refer to subtypes or supertypes of parameter types, e.g. G<? extends A> g1; // anything that is a subtype of A G<? super B> g2; // anything that is a supertype of B

  22. Generic Methods Like generic classes, we can declare generic methods that have one or more parametrized types.

  23. Generic Methods Like generic classes, we can declare generic methods that have one or more parametrized types. For example, we can write a generic method to print a Triple as follows: public static <T> void printTriple( Triple <T> tr ) { System.out.println( "" + tr.getX () + ’\n’ + tr.getY () + ’\n’ + tr.getZ () ); }

  24. Generic Methods Like generic classes, we can declare generic methods that have one or more parametrized types. For example, we can write a generic method to print a Triple as follows: public static <T> void printTriple( Triple <T> tr ) { System.out.println( "" + tr.getX () + ’\n’ + tr.getY () + ’\n’ + tr.getZ () ); } When calling a generic method, the type is automatically inferred, e.g. Triple <Integer > tr = new Triple <> (new Integer (1), new Integer (2), new Integer (3)); printTriple( tr ); // calls the generic method

  25. Example: Generic Insertion Sort To sort items, they have to be comparable. This is assured through the java.lang.Comparable<T> interface. We can use a generic method but restrict it to those types that implement the Comparable<T> interface: public <T extends Comparable <T>> void insertionSort ( T[] data ) { for(int i = 1, j; i < data.length; i++) { T tmp = data[i]; for(j = i; j > 0 && tmp.compareTo(data[j -1]) < 0; j--) data[j] = data[j -1]; data[j] = tmp; } }

  26. Caveats Cannot declare static fields whose types are generic: public class G<T> { private static T var; //not allowed //... }

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend