Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Java Generics • It is nice if we could write a single sort method that could sort array of any type of elements: – Integer array, – String array, • Solution: Generics! • Generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Advantages of Generics 1. Stronger type checks at compile time: – A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. 2. Elimination of casts. Using no generics requires casting: List list = new ArrayList(); list.add("hello"); String s = (String) list.get(0); Try this code in DrJava interaction pane. If you add an integer (say 3) will compiler complain? Using generics, require no casting: List<String> list = new ArrayList<String>(); list.add("hello"); Try this code in DrJava String s = list.get(0); interaction pane. If you add an integer (say 3) will compiler complain? No compiler error if you add different data-type elements Compiler error if you add different data-type element than one specified at the time of creating list (Strong type checking at compile time!) 3. Enabling programmers to implement generic algorithms. – By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read. – E.g. a single sort method that sort an array of any type element with ordering Generic Types • A generic type is a generic class or interface that is parameterized over types. • Let’s begin by examining a non-generic Box class that operates on objects of any type. • You are free to pass in whatever object you want to methods. • There is no way to verify, at compile time, how the class is used. – One part of the code may place an Integer in the box – Another part of the code may mistakenly pass in a String, resulting in a runtime error. A Generic Version of the Box Class • A generic class is defined with the following format: class name<T1, T2, ..., Tn> { /* ... */ } type parameters (type variables) T1, T2, ..., and Tn • With this change, the Box class becomes: – all occurrences of Object are replaced by T • A type variable can be any non-primitive type you specify: – any class type, – any interface type, – any array type, or even – another type variable. • This same technique can be applied to create generic interfaces. Type Parameter Naming Conventions • The most commonly used type parameter names are: – – – – – – E - Element (used extensively by Java Collections Framework) K - Key N - Number T - Type V - Value S,U,V etc. - 2nd, 3rd, 4th types Invoking and Instantiating a Generic Type • Perform a generic type invocation – replace T with some concrete value, such as Integer: Box<Integer> integerBox; – Similar to an ordinary method invocation, but instead of passing an argument to a method, you are passing a type argument —Integer in this case — to the Box class itself. • To instantiate this class, use the new keyword, as usual, but place <Integer> between the class name and the parenthesis: Box<Integer> integerBox = new Box<Integer>(); Programming Question • Write generic class Box. • Use following tester class to test. public class GenericsTester { public static void main(String args[]) { Box<Integer> integerBox = new Box<Integer>(); integerBox.set(new Integer(3)); Integer n = integerBox.get(); System.out.println(n); } } Answer Box.java /** * Generic version of the Box class. * @param <T> the type of the value being boxed */ public class Box<T> { // T stands for "Type" private T t; public void set(T t) { this.t = t; } public T get() { return t; } } public class GenericsTester { public static void main(String args[]) { Box<Integer> integerBox = new Box<Integer>(); integerBox.set(new Integer(3)); Integer n = integerBox.get(); System.out.println(n); } } Multiple Type Parameters • Generic class can have multiple type parameters. • E.g., the generic OrderedPair class, which implements the generic Pair interface: • The following statements create two instantiations of the OrderedPair class: – Due to autoboxing, it is valid to pass a String and an int to the class. • Above statements can be shortened using diamond notation: • To create a generic interface, follow the same conventions as for creating a generic class. Programming Question • Create Pair interface and OrderedPair generic class that implement it. • Then modify GenericsTester to create two ordered pair objects (as given in example) and print keys and values of both pairs. Answer public interface Pair<K, V> { public K getKey(); public V getValue(); } Pair.java OrderedPair.java public class OrderedPair<K, V> implements Pair<K, V> { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } } GenericsTester.java public class GenericsTester { public static void main(String args[]) { Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8); Pair<String, String> p2 = new OrderedPair<String, String>("hello", "world"); System.out.println("p1 key:"+p1.getKey()+" p1 value:"+p1.getValue()); System.out.println("p2 key:"+p2.getKey()+" p2 value:"+p2.getValue()); } } Parameterized Types • You can also substitute a type parameter (i.e., K or V) with a parameterized type (i.e., List<String>). • For example, using the OrderedPair<K, V> example: Raw Types • A raw type is the name of a generic class or interface without any type arguments. • To create a parameterized type of Box<T>: – you supply an actual type argument for the formal type parameter T: Box<Integer> intBox = new Box<>(); • To create a raw type of Box<T>: – Omit actual type argument Box rawBox = new Box(); • Raw types show up in legacy code because lots of API classes (such as the Collections classes) were not generic prior to JDK 5.0. • Read more: – http://docs.oracle.com/javase/tutorial/java/generics/rawT ypes.html Generic Methods • Methods that introduce their own type parameters. • type parameter's scope is limited to the method • The Util class includes a generic method, compare, which compares two Pair objects: • The complete syntax for invoking this method would be: • Generally, type can be left out and the compiler will infer the type (type inference): Programming Question • Modify the GenericsTester to implement a generic method printArray. The method should accept an array of a generic type (E or T) and print all array elements. Find code template next slide public class GenericsTester { public static void main(String args[]) { // Create arrays of Integer, Double and Character Integer[] intArray = { 1, 4, 3, 4, 5 }; Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 }; Character[] charArray = { 'H', 'E', 'L', 'L', 'O' }; System.out.println( "Array integerArray contains:" ); printArray( intArray ); // pass an Integer array System.out.println( "\nArray doubleArray contains:" ); printArray( doubleArray ); // pass a Double array System.out.println( "\nArray characterArray contains:" ); printArray( charArray ); // pass a Character array } //TODO: generic method printArray } Answer public class GenericsTester { public static void main(String args[]) { // Create arrays of Integer, Double and Character Integer[] intArray = { 1, 4, 3, 4, 5 }; Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 }; Character[] charArray = { 'H', 'E', 'L', 'L', 'O' }; System.out.println( "Array integerArray contains:" ); printArray( intArray ); // pass an Integer array System.out.println( "\nArray doubleArray contains:" ); printArray( doubleArray ); // pass a Double array System.out.println( "\nArray characterArray contains:" ); printArray( charArray ); // pass a Character array } // generic method printArray public static < E > void printArray( E[] inputArray ) { // Display array elements for ( E element : inputArray ){ System.out.printf( "%s ", element ); } System.out.println(); } } Bounded Type Parameters • Sometimes you want to restrict the kinds of types that are allowed to be passed to a type parameter. • E.g., a method that operates on numbers might only want to accept instances of Number or its subclasses. • Solution: use 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. Example public class MaximumTest { // determines the largest of three Comparable objects public static <T extends Comparable<T>> T maximum(T x, T y, T z) { T max = x; // assume x is initially the largest if ( y.compareTo( max ) > 0 ){ max = y; // y is the largest so far} if ( z.compareTo( max ) > 0 ){ max = z; // z is the largest now} return max; // returns the largest object } public static void main( String args[] ) { System.out.printf( "Max of %d, %d and %d is %d\n\n", 3, 4, 5, maximum( 3, 4, 5 ) ); System.out.printf( "Maxm of %.1f,%.1f and %.1f is %.1f\n\n", 6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) ); System.out.printf( "Max of %s, %s and %s is %s\n","pear", "apple", "orange", maximum( "pear", "apple", "orange" ) ); } } Programming Question • Modify class GenericsTester to implement generics version of selection sort method. Then call this on an Integer and a Double Array. • Non-generic version: public static int[] sort(int[] a) { int N = a.length; for (int i = 0; i < N; i++) { int min = i; for (int j = i+1; j < N; j++) { if ((a[j]<a[min]) { min = j; } int temp = a[i]; a[i]= a[min]; a[min]=temp; } return a; } } Find code template next slide public class SelectionSorter { //TODO: generic selection sort method public static void main(String args[]) { Integer[] intArray = {1,30,20, 10, 3}; intArray = sort(intArray); for(int n: intArray) System.out.print(" "+ n); } } Answer public class SelectionSorter { public static <T extends Comparable<T>> T[] sort(T[] a) { int N = a.length; for (int i = 0; i < N; i++) { int min = i; for (int j = i+1; j < N; j++) { if ((a[j].compareTo(a[min]))<0) { min = j; } } T temp = a[i]; a[i]= a[min]; a[min]=temp; } return a; } public static void main(String args[]) { Integer[] intArray = {1,30,20, 10, 3}; intArray = sort(intArray); for(int n: intArray) System.out.print(" "+ n); } } • Read more: – http://docs.oracle.com/javase/tutorial/java/gener ics/