CSC302 2007S, Class 24: Java Generics Admin: * Due: Mid-Semester Exam. * Thanks for your patience on Wednesday. Eldest son came in first, so we're off to state in a month. * Have a great break! Overview: * Limitations to Java's Strong Type Checking. * A (Partial) Solution: Java Generics. * Restricting Parameter Classes. * Subtleties. * Behind the Scenes. Review of Wednesday's Class * Inner classes are useful for small, special-purpose classes * Avoid classes * Special Syntax ClassName object = new ClassName() { BODY }; * Might simulate mutiple inheritance with mixins * Common uses? * Event handlers * Comparators for sorting routines /Another Java Technique: Generics (Parameterized Classes)/ * Context: "Java is your nanny" * Almost anything that is potential dangerous is disallowed * Compile time type checking * Exception handling FILE *input = fopen("user.dat"); if (NULL == input) { // Recover from errors exit(1); } scanf("%d", &i); * Use of variables before they are assigned * Flaw in original design: Collections (and related things) /** * Find a string whose length is no more than the other * strings in strings. * * @return * shortest, a String * @pre * strings contains only Strings * @pre * strings is nonempty * @post * shortest.length() <= strings.get(i).length() for all * i, 0 <= i < strings.size() * @post * Exists i, s.t. shortest = strings.get(i); */ String shortest(Vector strings) { String shortest = (String) strings.get(0); for (int i = 1; i < strings.size(); i++) { String tmp = (String) strings.get(i); if (tmp.length() < shortest.length()) { shortest = tmp; } // if } // for return shortest; } // shortest(Vector) * The 1.4 compiler does not verify that this is only called on vectors of strings * But if we believe the language should do type checking, it should be able to type check this, too. * Solution: Generics * Classes, interfaces, and methods can have type parameters * In Java 5, Vector is now Vector String shortest(Vector strings) { String shortest = strings.get(0); for (int i = 1; i < strings.size(); i++) { String tmp = strings.get(i); if (tmp.length() < shortest.length()) { shortest = tmp; } // if } // for return shortest; } // shortest(Vector) Vector foo = new Vector(); ... System.out.println(shortest(foo)); Vector bar = new Vector(); ... System.out.println(shortest(bar)); // FAILS TO COMPILE (YAY!) Defining our own parameterized classes public class Node { T car; Node cdr; } Consider our old friend the sorting algorithm /** * @return void * @pre * All the objects in the vector must be similar enough that * we can compare them * For any two objects in the vector, we can successfully * apply c.compare(o1,o2) * @post * The sortMe.final is a permutation of sortMe.initial WAS public void sort(Vector sortMe, Comparator c) NOW public void sort(Vector sortMe, Comparator c) Parameterized classes seem "simple", but complexities when combined with inheritance class A { ... } class B extends A { ... } Some variables and some assignments. Which should or should not be legal? A a = new A(); B b = new B(); Vector as = new Vector(); Vector bs = new Vector(); a = b; // You may use an element in a subclass in place of // an element in the superclass. b = a; // You may NOT use an element in a superclass in place // of an element in the subclass as.add(a); // Yes. A vector of A's should include A's. bs.add(a); // No. See b = a. as.add(b); // Yes. Same reason as a=b. bs.add(b); // Yes. A vector of B's should include B's. as = bs; // No. bs = as; // No. Similar to b = a Analysis of "as = bs;" * Suppose we permit the assignment * We should now be able to write as.add(a) * But as currently refers to a vector of Bs * And we shouldn't be able to put an A into a vector of Bs Moral: Subtyping does not propagate into parameterized classes * That is, if B is a subclass of A, Foo is NOT a subclass of Foo * Also applies to arrays * It is a PITA to write generic classes that use arrays /Detour: Implementation/ * Two choices * Change the JVM * "Syntactic sugar" * Second choice made because * Java 1.4 JVM widely installed * Making sure it gets replaced is a pain in two arms When programming with generics, you can also use public class Foo