RJUG : 12-Dec-2012                                                                                © Copyright 2012, Software Alchemy




                                  Java Generics
                                                               History
                                                              & Theory

                                                                                Creating a
                                        Odds & Sods
                                                                               Generic Class


                                                        Java Generics:
                                                         a Deep Dive
                                      Creating a                                     Creating a
                                        Generic                                    Generic Method
                                      Framework



                                              Generics in                 Recursive
                                              Frameworks                 Generic Types




                                                            Bryan Basham
                                                            Software Alchemy
                                                        basham47@gmail.com
                                             http://www.linkedin.com/in/SoftwareAlchemist

Bryan Basham – Java Generics: a Deep Dive                                                                                      Slide 1
RJUG : 12-Dec-2012                                                                                  © Copyright 2012, Software Alchemy




                                  History & Theory
                                                               Erasure     Wildcards & PECS
                                                   History
                                                                                 Mixing w/
                                                                                 Raw Types
                                                                 History
                                                                & Theory

                                                                                  Creating a
                                        Odds & Sods
                                                                                 Generic Class


                                                             Java Generics:
                                                              a Deep Dive
                                      Creating a                                       Creating a
                                        Generic                                      Generic Method
                                      Framework



                                              Generics in                   Recursive
                                              Frameworks                   Generic Types




Bryan Basham – Java Generics: a Deep Dive                                                                                        Slide 2
RJUG : 12-Dec-2012                                                © Copyright 2012, Software Alchemy




                                  Why Are Generics Important?

      ●     The great debate of dynamic vs static
            languages
                    –    Dynamic is great for rapid prototyping
                    –    Static is better for serious engineering
                    –    I love both, but...
      ●     This talk is about serious engineering, so...
                    –    Let the compiler catch more potential bugs
                    –    Apply more rigor to your designs
                    –    Add more flexibility to your designs
Bryan Basham – Java Generics: a Deep Dive                                                      Slide 3
RJUG : 12-Dec-2012                                            © Copyright 2012, Software Alchemy




                                  History

      ●     Generic types were introduced in J2SE 5.0 in
            2004
                    –    Additional type safety
                    –    Reduced the need for casting
      ●     Pre-generics code example:
      List v = new ArrayList();
      v.add(“test”);
      Integer i = (Integer) v.get(0);       // Run-time error

      ●     Post-generics:
      List<String> v = new ArrayList<String>();
      v.add(“test”);
      Integer i = v.get(0); // Compile-time error

Bryan Basham – Java Generics: a Deep Dive                                                  Slide 4
RJUG : 12-Dec-2012                                                        © Copyright 2012, Software Alchemy




                                  Theory

      ●     Unlike C++ templates
                    –    Primitives cannot be type parameters
                          List<int> numbers;   // not legal

                    –    Only one generated code file
      ●     Generics are a compile-time feature
                    –    At run-time type variables (eg T) become Object
                    –    This is called erasure
      public class LispList<T> {                          public class LispList {
         private T item;                                     private Object item;
         private LispList<T> next;                           private LispList next;
         public T first() {...}                              public Object first() {...}
         // etc...                                           // etc...
      }                                                   }
Bryan Basham – Java Generics: a Deep Dive                                                              Slide 5
RJUG : 12-Dec-2012                                                                    © Copyright 2012, Software Alchemy




                                  Terminology
                                            Type Parameter
      ●     Generic type:
      public class LispList<T> { ... }

      public class Pair<T1, T2> { ... }
                                                             Type Argument
      ●     Parameterized type:                              (required in Java 5 & 6)


      LispList<String> list = new LispList<String>("first");

      Pair<String,Integer> p1 = new Pair<String,Integer>("random number", 47);

      ●     Type inference in Java 7:
      Pair<String,Integer> p1 = new Pair<>("random number", 47);

      Map<FrequencyCategory,                    “the diamond”
          Map<RecencyCategory,
              EnumMap<RfmAnalysisStatistic, Number>>> rfmContent =
                 new HashMap<>();

Bryan Basham – Java Generics: a Deep Dive                                                                          Slide 6
RJUG : 12-Dec-2012                                                       © Copyright 2012, Software Alchemy




                                  More Terminology
                                            Wildcard Argument
      ●     Generic method:                 (unbounded)



      public void printPair(Pair<?,?> p) {
          System.out.println("(" + p.getFirst() + "," + p.getSecond() + ")");
      }
                                                   Upper-Bound Wildcard
      ●     Bounded wildcards:
      public interface DomainEntityDAO<T extends DomainEntity> {
          public long create(T entity);
          public T findById(long id);
      }

          Generic Method Type Parameter                   Lower-Bound Wildcard



      public static <T> void flush(Collection<T> coll, Sink<? super T> sink) {
          // flush all elements in the collection to the sink
      }


Bryan Basham – Java Generics: a Deep Dive                                                             Slide 7
RJUG : 12-Dec-2012                                                © Copyright 2012, Software Alchemy




                                  The PECS Principle

      ●     Producers use extends:
      public T something() { /* this method produces a T or subclasses */ }

      ●     Consumers use super:
      public void something(T) { /* this method consumes a T or ancestors */ }

      ●     So what?                                 The collection produces elements
                                                     to compare to find the max.
      // from the java.util.Collections API:

      public static <T> T max(Collection<? extends T> collection,
                              Comparator<? super T> comparator)


                                                    The comparator consumes elements
      ●     More explanation: click here            while performing the comparison.



Bryan Basham – Java Generics: a Deep Dive                                                      Slide 8
RJUG : 12-Dec-2012                                                       © Copyright 2012, Software Alchemy




                                  Mixing Raw Types with Generics

      ●     A raw type is a use of a generic type without
            type arguments:               Raw Type

                        List<String> list1 = new ArrayList();// legal, but with warnings
                        list1.add("abc");
                        list1.add(47);    // not legal

                    –    Compiler treats this as a list of strings (only); the
                          type info is on the variable not the RT object
                        @SuppressWarnings("rawtypes") // use this to suppress warnings
                        List<?> list3 = new ArrayList();
                        list3.add("abc");         // not legal
                        list3.add(47);            // not legal
                        list3.add(null);          // null is the only legal value

                    –    Compiler treats this as a list of unknown values

Bryan Basham – Java Generics: a Deep Dive                                                             Slide 9
RJUG : 12-Dec-2012                                                           © Copyright 2012, Software Alchemy




                                  Mixing Raw Types with Generics

      ●     More examples:
                        List list5 = new ArrayList<String>();
                        list5.add("abc"); // legal
                        list5.add(47);    // legal, but not type-safe

                    –    Compiler treats this as a list of anything
                        List list6 = new ArrayList<?>();   // compiler error

                    –    Not legal to use wildcards in instantiation syntax
      ●     Don't mix raw types with generic types
                    –    Unless integrating with legacy APIs
                    –    NEVER use raw types in new code

Bryan Basham – Java Generics: a Deep Dive                                                                Slide 10
RJUG : 12-Dec-2012                                                                                         © Copyright 2012, Software Alchemy




                                  Creating a Generic Class
                                                                 Erasure     Wildcards & PECS
                                                     History
                                                                                   Mixing w/
                                                                                   Raw Types
                                                                   History
                                                                                                Simple Ex
                                                                  & Theory
                                                                                                            Complex Ex
                                                                                    Creating a
                                            Odds & Sods
                                                                                   Generic Class            Multiple Type Params

                                                                                                   Other Types

                                                               Java Generics:
                                                                a Deep Dive
                                      Creating a                                         Creating a
                                        Generic                                        Generic Method
                                      Framework



                                                  Generics in                 Recursive
                                                  Frameworks                 Generic Types




Bryan Basham – Java Generics: a Deep Dive                                                                                              Slide 11
RJUG : 12-Dec-2012                                             © Copyright 2012, Software Alchemy




                                  A Simple Example

      ●     A class with one type parameter:
      public class Optional<T> {

               private final T item;

               public Optional(T item) {
                   this.item = item;
               }

               public boolean isPresent() {
                   return item != null;
               }
               public T or(T defaultValue) {
                   return item != null ? item : defaultValue;
               }
               public T get() {
                   if (item != null) { return item; }
                   else { throw new IllegalStateException(); }
               }
      }

Bryan Basham – Java Generics: a Deep Dive                                                  Slide 12
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  A Simple Example: Unit Tests

      ●     A class with one type parameter:
               @Test
               public void test() {
                   Integer item = null;
                   Optional<Integer> opt = new Optional<Integer>(item);
                   assertTrue(!opt.isPresent());
                   assertEquals(47, opt.or(47).intValue());
                   try { int value = opt.get(); fail(); }
                   catch (IllegalStateException e) { /* succeeds */ }

                       item = 42;
                       opt = new Optional<Integer>(item);
                       assertTrue(opt.isPresent());
                       assertEquals(42, opt.or(47).intValue());
                       assertEquals(42, opt.get().intValue());
               }

      ●     BTW, this is a hack of a real Guava class

Bryan Basham – Java Generics: a Deep Dive                                                       Slide 13
RJUG : 12-Dec-2012                                              © Copyright 2012, Software Alchemy




                                  Example: Classic link list

      ●     A LISP-like linked list implementation:
      public class LispList<T> {
          private final T head;
          private LispList<T> tail;

               public LispList(T head) {
                   this.head = head;
               }

               public T first() {
                   return head;
               }
               public LispList<T> rest() {
                   return tail;
               }
               public LispList<T> addToFront(T item) {
                   LispList<T> newHead = new LispList<T>(item);
                   newHead.tail = this;
                   return newHead;
               }
      }
Bryan Basham – Java Generics: a Deep Dive                                                   Slide 14
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  Example: Classic link list

      ●     Simple usage test:
               @Test
               public void testAdd() {
                   LispList<String> list = new LispList<String>("first");
                   list = list.addToFront("second");
                   list = list.addToFront("third");
                   list = list.addToFront("fourth");
                   // test the link chain
                   assertEquals("fourth", list.first()); // car
                   assertEquals("third", list.rest().first()); // cadr
                   assertEquals("second", list.rest().rest().first()); // caddr
                   assertEquals("first", list.rest().rest().rest().first());
               }




Bryan Basham – Java Generics: a Deep Dive                                                       Slide 15
RJUG : 12-Dec-2012                                                          © Copyright 2012, Software Alchemy




                                  Example: Classic link list

      ●     Use generic interfaces to extend behavior:
      public class LispList<T> implements Iterable<T> {
          // skip previous code
          @Override
          public Iterator<T> iterator() {
              return new LispListIterator<T>(this);
          }
          private static class LispListIterator<T> implements Iterator<T> {
              private LispList<T> currentHead;
              private LispListIterator(LispList<T> listHead) {
                  currentHead = listHead;
              }
              @Override
              public boolean hasNext() {
                  return currentHead != null;
              }
              @Override
              public T next() {
                  T item = currentHead.head;
                  currentHead = currentHead.tail;
                  return item;
              }
              @Override
              public void remove() {
                  throw new UnsupportedOperationException();
              }
          }
      }
Bryan Basham – Java Generics: a Deep Dive                                                               Slide 16
RJUG : 12-Dec-2012                                                          © Copyright 2012, Software Alchemy




                                  Example: Classic link list

      ●     Test the iterable behavior:
               @Test
               public void testAdd() {
                   LispList<Integer> list = new LispList<Integer>(0);
                   list.addToEnd(1);
                   list.addToEnd(2);
                   list.addToEnd(3);        You can use any Iterable as the
                   //                       target of a for-each statement.
                   int count = 0;
                   for (int value : list) {
                       assertEquals(count++, value);
                   }
               }




Bryan Basham – Java Generics: a Deep Dive                                                               Slide 17
RJUG : 12-Dec-2012                                     © Copyright 2012, Software Alchemy




                                  Using Multiple Type Params

      ●     A class with two type parameters:
      public class Pair<T1, T2> {

               private final T1 first;
               private final T2 second;

               public Pair(T1 o1, T2 o2) {
                   this.first = o1;
                   this.second = o2;
               }

               public T1 getFirst() {
                   return first;
               }

               public T2 getSecond() {
                   return second;
               }
      }


Bryan Basham – Java Generics: a Deep Dive                                          Slide 18
RJUG : 12-Dec-2012                                                      © Copyright 2012, Software Alchemy




                                  Using Multiple Type Args

      ●     Unit test for our Pair class:
               @Test
               public void test1() {
                   Pair<String, Long> p1 = new Pair<String, Long>("a test", 47L);
                   assertEquals("a test", p1.getFirst());
                   assertEquals(new Long(47), p1.getSecond());

                       // Java 7
                       Pair<String, Long> p2 = new Pair<>("life & everything", 42L);
                       assertEquals("life & everything", p2.getFirst());
                       assertEquals(new Long(42), p2.getSecond());
               }




Bryan Basham – Java Generics: a Deep Dive                                                           Slide 19
RJUG : 12-Dec-2012                                               © Copyright 2012, Software Alchemy




                                  Generic Interfaces

      ●     A generic function to determine the truth of
            some condition:
      public interface Predicate<T> {
          public boolean apply(T input);
      }
      private static final Predicate<Integer> IS_EVEN_P = new Predicate<>() {
          public boolean apply(Integer input) { return input % 2 == 0; }
      };

      ●     A generic function to transform an input from
            one value to another:
      public interface Function<FROM, TO> {
          public TO apply(FROM input);
      }

      ●     BTW, these are also part of Guava; one of my favorite Java libraries

Bryan Basham – Java Generics: a Deep Dive                                                    Slide 20
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  Predicate Unit Test

               @Test
               public void predicateTest() {
                   List<AppParameter> parameters = new ArrayList<>();
                   parameters.add(p1 = new AppParameter(PARAM1, VALUE1));
                   parameters.add(p2 = new AppParameter(PARAM2, VALUE2));
                   parameters.add(p3 = new AppParameter(PARAM3, VALUE3));
                   // change a few values
                   p1.setValue(NEW_VALUE1);
                   p2.setValue(NEW_VALUE2);
                   // test the "is dirty" function
                   Collection<AppParameter> dirtyList =
                           CollectionUtils.gather(parameters, new Predicate<>() {
                       @Override
                       public boolean apply(AppParameter input) {
                           return input.isDirty();
                       };
                   });
                   assertEquals(2, dirtyList.size());
               }




Bryan Basham – Java Generics: a Deep Dive                                                       Slide 21
RJUG : 12-Dec-2012                                    © Copyright 2012, Software Alchemy




                                  Other Generic Types

      ●     These types can be made generic...
                    –    Classes
                    –    Interfaces
                    –    Inner classes, etc
      ●     These Java types may not be generic:
                    –    Anonymous inner classes
                    –    Exceptions
                    –    Enums

Bryan Basham – Java Generics: a Deep Dive                                         Slide 22
RJUG : 12-Dec-2012                                                                                         © Copyright 2012, Software Alchemy




                                  Creating a Generic Method
                                                                 Erasure     Wildcards & PECS
                                                     History
                                                                                   Mixing w/
                                                                                   Raw Types
                                                                   History
                                                                                                Simple Ex
                                                                  & Theory
                                                                                                            Complex Ex
                                                                                    Creating a
                                            Odds & Sods
                                                                                   Generic Class            Multiple Type Params

                                                                                                   Other Types

                                                               Java Generics:
                                                                                                             Simple Ex
                                                                a Deep Dive
                                       Creating a                                        Creating a
                                         Generic                                       Generic Method             Complex Ex
                                       Framework
                                                                                                        PECS Reprised

                                                  Generics in                 Recursive
                                                  Frameworks                 Generic Types




Bryan Basham – Java Generics: a Deep Dive                                                                                              Slide 23
RJUG : 12-Dec-2012                                     © Copyright 2012, Software Alchemy




                                  Why Generic Methods?

      ●     Generic methods allow you to create
            algorithms that apply to a wide variety of types.
      ●     For example, how many sorting algorithms do
            you need?
                    –    Sort a list of integers
                    –    Sort a list of dates
                    –    Sort a list of strings
      ●     What do these all have in common?


Bryan Basham – Java Generics: a Deep Dive                                          Slide 24
RJUG : 12-Dec-2012                                                      © Copyright 2012, Software Alchemy




                                  A Simple Generic Method

      ●     Gather all items in a collection that satisfy the
            given predicate:
               public static <T> Collection<T> gather(final Iterable<T> collection,
                                                      final Predicate<T> predicate)
      {

                       checkNotNull(collection, "collection must not be null");
                       checkNotNull(predicate, "predicate must not be null");

                       Collection<T> result = new ArrayList<T>();
                       for (T item : collection) {
                           if (predicate.apply(item)) {
                               result.add(item);
                           }
                       }
                       return result;
               }



Bryan Basham – Java Generics: a Deep Dive                                                           Slide 25
RJUG : 12-Dec-2012                                                                © Copyright 2012, Software Alchemy




                                  A gather Method Unit Test

               @Test
               public void testGather() {
                   // Gather negative numbers
                   Collection<Integer> test1 =
                       CollectionUtils.gather(Arrays.asList(TEST_NUMS), IS_NEG);
                   assertEquals(test1.size(), NEG_NUMBERS_ARRAY.length);
                   for (Integer n : NEG_NUMBERS_ARRAY) {
                       assertTrue("elements are correct", test1.contains(n));
                   }
               }
               private static final Integer[] TEST_NUMS = {
                   -42, 42, 0, 13, -47, 42, 42, 47
               };
               private static final Integer[] NEG_NUMBERS_ARRAY = { -42, -47 };
               private static final Predicate<Integer> IS_NEG = new Predicate<>() {
                   public boolean apply(Integer input) { return input < 0; }
               };



                                            Does anyone see the bug in this code?


Bryan Basham – Java Generics: a Deep Dive                                                                     Slide 26
RJUG : 12-Dec-2012                                                      © Copyright 2012, Software Alchemy




                                  A More Complex Example

      ●     A mapping operation:
               public static <F, T> Collection<T> map(
                         final Collection<F> collection,
                         final Function<F, T> transformer) {

                       checkNotNull(collection, "collection must not be null");
                       checkNotNull(transformer, "transformer must not be null");

                       Collection<T> result = new ArrayList<T>();
                       for (F item : collection) {
                           result.add(transformer.apply(item));
                       }
                       return result;
               }




Bryan Basham – Java Generics: a Deep Dive                                                           Slide 27
RJUG : 12-Dec-2012                                                                    © Copyright 2012, Software Alchemy




                                  A More Complex Example

               @Test
               public void testMap() {
                   // Square all of the test numbers
                   Collection<Integer> test1 =
                       CollectionUtils.map(TEST_NUMBERS, SQUARE);
                   assertEquals(test1.size(), TEST_NUMBERS.size());
                   Iterator<Integer> numbers = TEST_NUMBERS.iterator();
                   Iterator<Integer> squares = test1.iterator();
                   while (numbers.hasNext()) {
                       int n = numbers.next().intValue();
                       int square = squares.next().intValue();
                       assertEquals("elements are correct", n * n, square);
                   }
               }
               private static final Function<Integer, Integer> SQUARE =
                                                 new Function<Integer, Integer>() {
                   public Integer apply(Integer x) { return x * x; }
               };

                                            The compiler requires type arguments for
                                            anonymous inner classes; that was the bug
                                            two slides ago.

Bryan Basham – Java Generics: a Deep Dive                                                                         Slide 28
RJUG : 12-Dec-2012                               © Copyright 2012, Software Alchemy




                                  PECS Reprised

      ●     So... what about that sorting problem? Can we
            create a single algorithm for all of these (and
            more)?
                    –    Sort a list of integers
                    –    Sort a list of dates
                    –    Sort a list of strings
      ●     What do these all have in common?
      ●     How does this relate to the Producer-extends,
            Consumer-super principle?
Bryan Basham – Java Generics: a Deep Dive                                    Slide 29
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  And now the answer...

      ●     Sorting requires that the objects in the
            collection are “comparable” to each other:
               public static <T extends Comparable<? super T>> void sort(
                         List<T> list) {
                   Object[] a = list.toArray();
                   Arrays.sort(a);
                   ListIterator<T> i = list.listIterator();
                   for (int j=0; j<a.length; j++) {
                       i.next();
                       i.set((T)a[j]);
                   }
               }

      ●     ...of course, this algorithm is kind-of cheating
            because it really sorts an array of Objects
            and that method uses casts to Comparable.
Bryan Basham – Java Generics: a Deep Dive                                                       Slide 30
RJUG : 12-Dec-2012                                                                                           © Copyright 2012, Software Alchemy




                                  Recursive Generic Types
                                                                 Erasure      Wildcards
                                                     History
                                                                                    Mixing w/
                                                                                    Raw Types
                                                                   History
                                                                                                Simple Ex
                                                                  & Theory
                                                                                                            Complex Ex
                                                                                     Creating a
                                            Odds & Sods
                                                                                    Generic Class           Multiple Type Params

                                                                                                   Other Types

                                                               Java Generics:
                                                                                                               Simple Ex
                                                                a Deep Dive
                                       Creating a                                           Creating a
                                         Generic                                          Generic Method            Complex Ex
                                       Framework
                                                                                                        PECS Reprised

                                                  Generics in                 Recursive
                                                  Frameworks                 Generic Types
                                                                                                   Simple Ex


                                                                                           Enums
                                                                           Class




Bryan Basham – Java Generics: a Deep Dive                                                                                                Slide 31
RJUG : 12-Dec-2012                                          © Copyright 2012, Software Alchemy




                                  Recursive Generic Types

      ●     “A recursive generic type is any type that
            makes use of a generic type that has a type
            argument that refers to the original type.” (me)
      ●     This is not part of the formal definition of Java
            generics, but I find the concept useful.
                    –    Because they pop-up every so often
                    –    And cause problems if you don't handle them
                          correctly



Bryan Basham – Java Generics: a Deep Dive                                               Slide 32
RJUG : 12-Dec-2012                                             © Copyright 2012, Software Alchemy




                                  A Quasi-Recursive Generic

      ●     The Comparable interface forms a quasi-
            recursive generic. For example:
      public class RevenueBand implements Comparable<RevenueBand> {

              private String name;
              private int lowerBound;
              private int upperBound;

               @Override
               public int compareTo(RevenueBand that) {
                   return this.lowerBound – that.lowerBound;
               }
      }

      revBand1 = new RevenueBand("<$1M",                    0,     1_000_000);
      revBand2 = new RevenueBand("$1M - $10M",      1_000_000,    10_000_000);
      revBand3 = new RevenueBand("$10M - $50M",    10_000_000,    50_000_000);
      assertTrue(revBand1.compareTo(revBand2) < 0);


Bryan Basham – Java Generics: a Deep Dive                                                  Slide 33
RJUG : 12-Dec-2012                                          © Copyright 2012, Software Alchemy




                                  Enums

      ●     Java enums are special types that always
            extend Enum, which is defined as:
      public abstract class Enum<E extends Enum<E>>
              implements Comparable<E>, Serializable {
      ...
      }

      ●     This recursive definition guarantees that no
            enum class may extend any other class.
                    –    Of course, the compiler guarantees that because
                          the extends (subclass clause) cannot be used
                          in an enum definition:
      public enum Enum { A, B, C }

Bryan Basham – Java Generics: a Deep Dive                                               Slide 34
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  Using Enums in Generic
                                  Methods
      ●     The generics idiom T extends Enum<T> is
            used frequently in code involving enums:
               public static <T extends Enum<T>> Function<String, T> valueOfFunct(
                       final Class<T> enumClass) {
                   return new Function<String, T>() {
                       public T apply(String value) {
                           return Enum.valueOf(enumClass, value);
                       }
                   };
               }

               enum MyEnum { A, B, C }
               @Test
               public void test() {
                   Function<String, MyEnum> myFunc = valueOfFunct(MyEnum.class);
                   assertEquals(MyEnum.B, myFunc.apply("B"));
               }

      ●     Notice the use of the enumClass argument...
Bryan Basham – Java Generics: a Deep Dive                                                       Slide 35
RJUG : 12-Dec-2012                                   © Copyright 2012, Software Alchemy




                                  The Class Class

      ●     The ultimate recursive generic type is Class.
      ●     From the compiler's perspective:
                    – MyClass.class instanceof Class<MyClass>

      ●     Of course at run-time:
                    – MyClass.class instanceof Class

      ●     ...and as you just saw classes are frequently
            used to “identify” a type parameter on a
            generic method

Bryan Basham – Java Generics: a Deep Dive                                        Slide 36
RJUG : 12-Dec-2012                                                                                              © Copyright 2012, Software Alchemy




                                  Generics in Frameworks
                                                                  Erasure       Wildcards & PECS
                                                      History
                                                                                      Mixing w/
                                                                                      Raw Types
                                                                    History
                                                                                                   Simple Ex
                                                                   & Theory
                                                                                                               Complex Ex
                                                                                       Creating a
                                            Odds & Sods
                                                                                      Generic Class            Multiple Type Params

                                                                                                      Other Types

                                                                Java Generics:
                                                                                                                  Simple Ex
                                                                 a Deep Dive
                                       Creating a                                           Creating a
                                         Generic                                          Generic Method               Complex Ex
                                       Framework
                                                                                                           PECS Reprised

                                                  Generics in                   Recursive
                                                  Frameworks                   Generic Types
                                  GWT                                                                 Simple Ex

                                                                Guava
                                                 Spring                       Class        Enums




Bryan Basham – Java Generics: a Deep Dive                                                                                                   Slide 37
RJUG : 12-Dec-2012                                          © Copyright 2012, Software Alchemy




                                  Libraries to Consider

      ●     Guava
                    –    Google's answer to Apache Commons
      ●     Spring
                    –    The ubiquitous, light-weight, enterprise
                          framework for Java (Java EE replacement)
      ●     Google Web Toolkit
                    –    Modern Java-to-JavaScript bridge framework for
                          building advanced, single-page Web GUIs


Bryan Basham – Java Generics: a Deep Dive                                               Slide 38
RJUG : 12-Dec-2012                                  © Copyright 2012, Software Alchemy




                                  The Guava Library




Bryan Basham – Java Generics: a Deep Dive                                       Slide 39
RJUG : 12-Dec-2012                                              © Copyright 2012, Software Alchemy




                                  Guava Fundamentals

      ●     Optional: holds an optional value
      ●     Predicate: an interface for a query function
      ●     Function: an interface for a generic mapping
            operation
                    –    Here's a neat little higher-order operation:
               public static <A, B, C> Function<A, C> compose(
                       final Function<B, C> g,
                       final Function<A, B> f) {
                   return new Function<A, C>() {
                       public C apply(A a) {
                           return g.apply(f.apply(a));
                        }
                   };
               }

Bryan Basham – Java Generics: a Deep Dive                                                   Slide 40
RJUG : 12-Dec-2012                                                       © Copyright 2012, Software Alchemy




                                  Function Composition Unit Test

               enum MyEnum { A, B, C }

               @Test
               public void test() {
                   Function<String, MyEnum> myEnumFunc =
                            Enums.valueOfFunction(MyEnum.class);

                       Function<String, String> upperCaseFunc =
                                new Function<String, String>() {
                           public String apply(String s) { return s.toUpperCase(); }
                       };

                       Function<String, MyEnum> cleanEnumFunc =
                                Functions.compose(myEnumFunc, upperCaseFunc);

                       assertEquals(MyEnum.B, cleanEnumFunc.apply("b"));
               }




Bryan Basham – Java Generics: a Deep Dive                                                            Slide 41
RJUG : 12-Dec-2012                                                                          © Copyright 2012, Software Alchemy




                                  Guava Collections

      ●       Range<C extends Comparable>
                    –    A range (or "interval") defines the boundaries around a contiguous span of values of
                            some Comparable type; for example, "integers from 1 to 100 inclusive."

      ●       Multiset<T>
                    –    A collection that supports order-independent equality, like Set, but may have duplicate
                            elements.

      ●       Multimap<K,V>
                    –    A collection that maps keys to values, similar to Map, but in which each key may be
                            associated with multiple values.

      ●       BiMap<K,V>
                    –    A bimap (or "bidirectional map") is a map that preserves the uniqueness of its values
                            as well as that of its keys.

Bryan Basham – Java Generics: a Deep Dive                                                                               Slide 42
RJUG : 12-Dec-2012                                                                         © Copyright 2012, Software Alchemy




                                  Guava Collections

      ●       Collections2
                    –      transform(Collection<F>, Function<? super F, T> function)

                                     : Collection<T> : creates a new collection of transformed elements

                    –       filter(Collection<T>, Predicate<T> function)
                                : Collection<T> : creates a new collection of selected elements

                    –    And a few more...




Bryan Basham – Java Generics: a Deep Dive                                                                              Slide 43
RJUG : 12-Dec-2012                                                                        © Copyright 2012, Software Alchemy




                                  Guava Collections

      ●       Iterables
                    –      boolean all(Collection<T> c, Predicate<T> predicate)
                             : queries whether all elements satisfy the predicate

                    –      boolean any(Collection<T> c, Predicate<T> predicate)
                             : queries whether any element satisfies the predicate

                    –      T find(Collection<T> c, Predicate<T> predicate, T defValue)
                             : finds the first value that satisfies the predicate, or returns the default

                    –      Optional<T> tryFind(Collection<T> c, Predicate<T> predicate)
                             : optionally finds the first value that satisfies the predicate

                    –      Lots more...


Bryan Basham – Java Generics: a Deep Dive                                                                             Slide 44
RJUG : 12-Dec-2012                              © Copyright 2012, Software Alchemy




                                  Guava Caching

      ●     Simple API to provide in-memory caching
      ●     Cache<K,V>: is a cache of keys to values
      ●     CacheLoader<K,V>: is a mechanism to load
            cache values
      ●     Use a CacheBuilder to construct and
            configure a cache




Bryan Basham – Java Generics: a Deep Dive                                   Slide 45
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  Guava Caching Example

               private Cache<String, WarehouseHealth> pwhHealthCache;
               @PostConstruct
               private void initializeService() {
                   int ttlInSeconds = SpringPropertyUtils.getIntProperty(
                           PWH_HEALTH_CACHE_TTL, DEFAULT_PWH_HEALTH_CACHE_TTL);
                   pwhHealthCache =
                           CacheBuilder.newBuilder()
                           .expireAfterWrite(ttlInSeconds, TimeUnit.SECONDS)
                           .build(new CacheLoader<String, WarehouseHealth>() {
                               @Override
                               public WarehouseHealth load(final String key) {
                                   List<ChannelHealth> channels =
                                           pwhPrimaryDAO.getChannelHealth();
                                   List<String> disabledProducts =
                                           pwhPrimaryDAO.getDisabledContentSets();
                                   boolean isFileWatcherRunning =
                                           pwhPrimaryDAO.isFileWatcherRunning();
                                   return new WarehouseHealth(channels,
                                                          disabledProducts,
                                                          isFileWatcherRunning);
                               }
                           });
               }
Bryan Basham – Java Generics: a Deep Dive                                                       Slide 46
RJUG : 12-Dec-2012                                   © Copyright 2012, Software Alchemy




                                  The Spring Library




Bryan Basham – Java Generics: a Deep Dive                                        Slide 47
RJUG : 12-Dec-2012                                                                           © Copyright 2012, Software Alchemy




                                  Spring's Context and Bean Ops

      ●     ApplicationContext and BeanFactory
                    –      T getBean(String beanName, Class<T> requiredType)

                                : retrieves a Spring declared bean (creates it if necessary)

      ●     BeanUtils
                    –      T instantiate(Class<T> clazz)
                             : creates a new instance of the bean using the no-arg constructor

                    –       T instantiateClass(Constructor<T> clazz, Object... args)
                             : creates a new instance of a bean with a specified constructor and arguments




Bryan Basham – Java Generics: a Deep Dive                                                                                Slide 48
RJUG : 12-Dec-2012                                          © Copyright 2012, Software Alchemy




                                  Spring's JdbcTemplate

      ●     If you are not using an ORM tool like Hibernate
            or JPA, you should use Spring's JDBC
            template API
                    –    Removes boilerplate JDBC code
                    –    Converts SQLException into more useful, but
                          silent exceptions
                    –    Allows you to focus on the SQL and data
                           conversion
                    –    RowMapper<T> is used to convert a single
                          ResultSet row into some Java object
Bryan Basham – Java Generics: a Deep Dive                                               Slide 49
RJUG : 12-Dec-2012                                                        © Copyright 2012, Software Alchemy




                                  Spring's JdbcTemplate

      ●     General Queries
                    –      List<T> query(String sql, Object[] args, RowMapper<T> mapper)

                    –      T query(String sql, Object[] args, ResultSetExtractor<T> rse)

      ●     Single Result Queries
                    –      T queryForObject(String sql, Object[] args, Class<T> clazz)

                    –      T queryForObject(String sql, Object[] args, RowMapper<T>
                            mapper)

      ●     Multiple Result Queries
                    –      List<T> queryForList(String sql, Object[] args, Class<T>
                            elementType)
Bryan Basham – Java Generics: a Deep Dive                                                             Slide 50
RJUG : 12-Dec-2012                                             © Copyright 2012, Software Alchemy




                                  JdbcTemplate Example

      public NovusNodeHealth getNovusHealth() {
          return getJdbcTemplate().queryForObject(
                 NOVUS_HEALTH_QUERY, novusHealthMapper);
      }

      private static final String NOVUS_HEALTH_QUERY =
          "SELECT novus_status, dm_load_key FROM etl_promote_status WHERE"
        + " dm_load_key in (SELECT max(dm_load_key) FROM etl_promote_status)";

      private final RowMapper<NovusNodeHealth> novusHealthMapper =
                new RowMapper<NovusNodeHealth>() {
         public NovusNodeHealth mapRow(final ResultSet rs, final int rowNum)
                  throws SQLException {
              Integer loadKey = rs.getInt("dm_load_key");
              String status = rs.getString("novus_status");
              return new NovusNodeHealth(status, loadKey, "NOVUS");
          }
      };




Bryan Basham – Java Generics: a Deep Dive                                                  Slide 51
RJUG : 12-Dec-2012                                © Copyright 2012, Software Alchemy




                                  The GWT Library




Bryan Basham – Java Generics: a Deep Dive                                     Slide 52
RJUG : 12-Dec-2012                                                                    © Copyright 2012, Software Alchemy




                                  GWT RPC Mechanism

                        Desktop                                                        Server
                                                          HTTP

  User
                       ...........
                       ...........
                       ...........                       «interface»
                                                  PubDatamartRPCAsync

                                            +getStationHealth(boolean,
                                             AsyncCallback<PubDmNodeHealthDTO>)
                                             : void
                                            +stopPublishingNode(
                                              AsyncCallback<Void>)
                                             : void


                «interface»                                                             «class»
             PubDatamartRPC                                                       PubDatamartRPCImpl

  +getStationHealth(boolean)                                                 +getStationHealth(boolean)
   : PubDmNodeHealthDTO                                                       : PubDmNodeHealthDTO
  +stopPublishingNode()                                                      +stopPublishingNode()
   : void                                                                     : void


Bryan Basham – Java Generics: a Deep Dive                                                                         Slide 53
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  GWT RPC

      ●
            AsyncCallback                   is the heart of RPC mechanism:
      public interface AsyncCallback<T> {
          void onSuccess(T result);
          void onFailure(Throwable caught);
      }

      ●     Usage:
               AsyncCallback<PublishingDmNodeHealthDTO> callback =
                          new AsyncCallback<PublishingDmNodeHealthDTO>() {
                   public void onSuccess(final PublishingDmNodeHealthDTO result) {
                       pubHealthNode = result;
                       // TODO refresh GUI
                   }
                   public void onFailure(Throwable exception) {
                      // TODO handle exception
                   }
               };
               PublishingDatamartRPC.Util.getInstance()
                   .getStationHealth(true, callback);
Bryan Basham – Java Generics: a Deep Dive                                                       Slide 54
RJUG : 12-Dec-2012                                            © Copyright 2012, Software Alchemy




                                  GWT DataGrid

      ●     DataGrid<T>
                    –    A table with headers and rows
                    –    T is the type of each row
      ●     Column<T, C>:
                    –    A single column in the grid
                    –    T is the row type and C is the column type
      ●     Cell<C>:
                    –    Defines how the cells in the grid are rendered
                    –    C is the column type
Bryan Basham – Java Generics: a Deep Dive                                                 Slide 55
RJUG : 12-Dec-2012                                             © Copyright 2012, Software Alchemy




                                  GWT DataGrid Example

      usersGrid = new DataGrid<UserDTO>();



      Column<UserDTO, String> userIdCOL =
                new Column<UserDTO, String>(editUserLinkCell) {
          public String getValue(final UserDTO row) {
              return row.getUserName();
          }
      };
      userNameCOL.setSortable(false);
      userNameCOL.setCellStyleNames("columnLeft");
      usersGrid.addColumn(userNameCOL, "Username");
      usersGrid.setColumnWidth(userNameCOL, USERNAME_COL_SIZE, Unit.PCT);



      private final Cell<String> editUserLinkCell = new AnchorTextCell() {
          protected void handleClick(final Context ctx, final String value) {
              EditUserPage.makeHistoryCommand(value).invoke();
          }
      };


Bryan Basham – Java Generics: a Deep Dive                                                  Slide 56
RJUG : 12-Dec-2012                                                                                              © Copyright 2012, Software Alchemy




                                  Creating a Generic Framework
                                                                  Erasure       Wildcards & PECS
                                                      History
                                                                                      Mixing w/
                                                                                      Raw Types
                                                                    History
                                                                                                   Simple Ex
                                                                   & Theory
                                                                                                               Complex Ex
                                                                                       Creating a
                                            Odds & Sods
                                                                                      Generic Class            Multiple Type Params

                                                                                                      Other Types
                Subsystem                                       Java Generics:
                Frameworks                                                                                        Simple Ex
                                                                 a Deep Dive
                                       Creating a                                           Creating a
                                         Generic                                          Generic Method               Complex Ex
              Multi-tier
                                       Framework
              Frameworks
                                                                                                           PECS Reprised
                          Simple Ex
                                                  Generics in                   Recursive
                                                  Frameworks                   Generic Types
                                  GWT                                                                 Simple Ex

                                                                Guava
                                                 Spring                       Class        Enums




Bryan Basham – Java Generics: a Deep Dive                                                                                                   Slide 57
RJUG : 12-Dec-2012                                           © Copyright 2012, Software Alchemy




                                  Building a Generic Framework

      ●     Frameworks appear in all applications, large
            and small
      ●     Look for redundant code and find a common
            abstraction
                    –    Sometimes this will be an abstract superclass
                    –    Sometimes a generic class
                    –    Sometimes a generic algorithm
                    –    Sometimes a generic architectural metaphor
                    –    Sometimes a shared subsystem abstraction

Bryan Basham – Java Generics: a Deep Dive                                                Slide 58
RJUG : 12-Dec-2012                                     © Copyright 2012, Software Alchemy




                                  Let's start small...

      ●     Database query request/response that
            supports paging, sorting and filtering
      ●     QueryRequest: provides input about the size
            and starting point of the page to query
      ●     QueryResult<T>: provides a single page of
            data from the query
      ●     PagedRowMapper<T>: extends Spring's
            RowMapper to provide the total count of the
            overall query
Bryan Basham – Java Generics: a Deep Dive                                          Slide 59
RJUG : 12-Dec-2012                                                                     © Copyright 2012, Software Alchemy




                                  Paged Queries Framework

                             «value object»
                           QueryRequest
                       pageStart : int
                       pageSize : int




           «Service»               retrieve(QueryRequest):       «DAO»
         MyService                 QueryResponse<MyEntity>      MyDAO                         Database




                                              T=MyEntity                    T=MyEntity
                             «value object»
                             QueryResult                         «helper»                   «entity»
                                                             PagedRowMapper               MyEntity
                       totalCount : int
                       page : List<T>


Bryan Basham – Java Generics: a Deep Dive                                                                          Slide 60
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  The QueryResult Class

      public class QueryResult<T> implements Serializable, Iterable<T> {

               private final int totalCount;
               private final List<T> items;

               public QueryResult(final int totalCountIn, final List<T> itemsIn) {
                   this.totalCount = totalCountIn;
                   this.items = itemsIn;
               }

               public final int getTotalCount() {
                   return this.totalCount;
               }
               public final List<T> getItems() {
                   return this.items;
               }

               @Override
               public final Iterator<T> iterator() {
                   return this.items.iterator();
               }
      }

Bryan Basham – Java Generics: a Deep Dive                                                       Slide 61
RJUG : 12-Dec-2012                                                   © Copyright 2012, Software Alchemy




                                  The QueryResult Class

      public abstract class PagedRowMapper<T> implements RowMapper<T> {

               private Integer totalCount = null;

               public Integer getTotalCount() {
                   return (this.totalCount != null) ? this.totalCount : 0;
               }

               @Override
               public final T mapRow(final ResultSet rs, final int rowNum)
                      throws SQLException {
                   if (this.totalCount == null) {
                       this.totalCount = rs.getInt("totalCount");
                   }
                   return mapEntity(rs, rowNum);
               }

               public abstract T mapEntity(ResultSet rs, int rowNum)
                      throws SQLException;
      }



Bryan Basham – Java Generics: a Deep Dive                                                        Slide 62
RJUG : 12-Dec-2012                                                                      © Copyright 2012, Software Alchemy




                                  A Multi-tier Framework

      ●     A simple “data entry” application can take
            advantage of the concept of an “Entity” (with
            CRUD operations) across all application tiers:


                            «GWT»                    «GWT RPC»     «Service»           «DAO»
                            MyGUI           HTTP      MyRPC        MySvc               MyDAO                DB
      User

                                                      «helper»
                                                   MyTransformer
                              «DTO»                                            «JPA»
                        MyEntityDTO                                       MyEntity




Bryan Basham – Java Generics: a Deep Dive                                                                           Slide 63
RJUG : 12-Dec-2012                                                                                  © Copyright 2012, Software Alchemy




                                  A Multi-tier Framework
                                                                    T                      T                          T,ID
                                                      «interface»          «interface»            «interface»
                                                    DomainEntity         DomainEntity           DomainEntity
                                                       RPC                 Service                 DAO
                                                                                               +create(T):ID
                                                                                               +findById(ID):T
                                                                                               +update(T)
                                                                                               +delete(T)


                                 T=User
                       «interface»
                       UserRPC                                      T                      T                    T,ID=Long
                                                       «class»              «class»                «class»
                                                   AbstractDomain       AbstractDomain         AbstractDomain
                                                    EntityRpcImpl        EntityService           EntityDAO



                                                            T=User                T=User                    T=User
                                                     «GWT RPC»
                       «GWT»                                               «Service»               «DAO»
                                                      UserRpc                                                                  DB
                  UserPage                  HTTP                           UserSvc                UserDAO
                                                        Impl
User

                       «DTO»                           «helper»                   «JPA»
                    UserDTO                        UserToDtoTfm                    User
Bryan Basham – Java Generics: a Deep Dive                                                                                       Slide 64
RJUG : 12-Dec-2012                                                 © Copyright 2012, Software Alchemy




                                  A Multi-tier Framework: the
                                  Interfaces
      public interface DomainEntity {
          public Long getId();
          public void setId(Long id);
          public boolean isNew();
          // other metadata properties
      }

      public interface DomainEntityDAO<T extends DomainEntity,
                                        ID extends Serializable> {
          public ID create(T entity);
          public T findById(ID id);
          public boolean delete(T entity);
          public void update(T entity);
      }

      public interface DomainEntityService<T extends DomainEntity> {
          public EntityResponse<T> create(T entity);
          public EntityResponse<T> retrieveById(Long entityId);
          public ServerResponse update(T entity);
          public ServerResponse delete(Long entityId);
      }



Bryan Basham – Java Generics: a Deep Dive                                                      Slide 65
RJUG : 12-Dec-2012                                             © Copyright 2012, Software Alchemy




                                  A Multi-tier Framework: the
                                  Interfaces
      public interface EntityDTO extends Model, IsSerializable {
          public static enum Depth { SURFACE, SUMMARY, TREE, DEEP };
          public Long getId();
          public void setId(Long id);
          public Depth getDepth();
          public void setDepth(Depth depth);
          public boolean isNew();
          public void merge(EntityDTO dto);
      }

      public interface DomainEntityRPC<DTO extends EntityDTO> {
          public abstract GuiEntityResponse<DTO> create(DTO entity);
          public abstract GuiEntityResponse<DTO> retrieveById(Long id);
          public abstract GuiServerResponse update(DTO entity);
          public abstract GuiServerResponse delete(Long id);
      }

      public interface DomainEntityRpcAsync<DTO extends EntityDTO> {
          void create(DTO entity, AsyncCallback<GuiEntityResponse<DTO>> c);
          void retrieveById(Long id, AsyncCallback<GuiEntityResponse<DTO>> c);
          void update(DTO entity, AsyncCallback<GuiServerResponse> c);
          void delete(Long id, AsyncCallback<GuiServerResponse> c);
      }
Bryan Basham – Java Generics: a Deep Dive                                                  Slide 66
RJUG : 12-Dec-2012                                                           © Copyright 2012, Software Alchemy




                                  Subsystem Framework Example

      ●     The Incentives framework supports three
            concrete subsystems in a financial application
                    –    Apps main function is supply chain analysis
                                 ●   Sales line item data
                                 ●   Plus lots of reference data: products, pricing
                                      catalogs, customers, etc
                    –    Incentives provides decision support
                                 ●   SPA: special pricing catalog assignment
                                 ●   Rebates: identify SLIs for rebates to resellers
                                 ●   SCA: sales rep commissions

Bryan Basham – Java Generics: a Deep Dive                                                                Slide 67
RJUG : 12-Dec-2012                                                                                        © Copyright 2012, Software Alchemy




                                  Incentives Framework Concepts
                                                      Program
                                                                   Contains inference and
                                                                     calculation rules.


                                     GUI Summary
                                                                                     Rules
                                       objects

                                                                                               Inference rules
                                                                                            generate associations.



                                                     Incentive's
                                                       Domain
                            Metadata                                                             Association
                                                        Model
                                                     mind-map
                                                                                Calculation rules
                                                                               generate calculation
                                                                                     results.




                                            Entity                               CalcResult



                                                     Transaction


Bryan Basham – Java Generics: a Deep Dive                                                                                             Slide 68
RJUG : 12-Dec-2012                                                                          © Copyright 2012, Software Alchemy




                                  Incentives “Programs” Flow
                            Nucleus


                                    Txn

                                                   Eligibility
                                                                   Association<Txn,Program>


                                             Txn


                                                Assignment
                                                                    Association<Txn,Entity>


                                            Entity



                                                   Calculation
                                                                       CalculationResult



                              Entity

                                                   Adjustment
                                                                 CalculationResult#AuditRecord

Bryan Basham – Java Generics: a Deep Dive                                                                               Slide 69
RJUG : 12-Dec-2012                                                     © Copyright 2012, Software Alchemy




                                  Incentives Analysis Model

                       ProgramSummary

                                                 Abstract           Rebates
                                              ProgramService      ProgramDAO

                        ProgramEditor



                                               DataService       DataServiceDAO
                          ProgramTest



                                            TransactionService   TransactionDAO
                        ProgramReview




                     EligibilityEditor            Rebates           Rebates
                                             ExecutionService     ExecutionDAO




                             ReRater

Bryan Basham – Java Generics: a Deep Dive                                                          Slide 70
RJUG : 12-Dec-2012                                                                                                © Copyright 2012, Software Alchemy




                                   Incentives Execution Services
                          «interface»
                          Service




                                            T extends Entity
                          «interface»
               IncentiveExecution                                                       «abstract»
                     Service                                                     AbstractBaseService




                                                                                        «abstract»   T extends Entity
                                                                                  AbstractIncentive
                           T=ProfileEntity
                                                                                  ExecutionService
            «interface»
    RebatesExecution
        Service
 +generatePayoutPayment
 +getPaymentHistory



                                                                             T=ProfileEntity                                T=SpaCatalogRecord
                                                          «nucleusService»                               «nucleusService»
                                                       RebatesExecution                                 SpaExecution
                                                         ServiceImpl                                     ServiceImpl

Bryan Basham – Java Generics: a Deep Dive                                                                                                     Slide 71
RJUG : 12-Dec-2012                                                                                              © Copyright 2012, Software Alchemy




                                  Odds & Sods
                                                                  Erasure       Wildcards & PECS
                                                      History
                                                                                      Mixing w/
                                                                                      Raw Types
                                       Reflection                   History
                                                                                                   Simple Ex
                                                                   & Theory
                    When not to
                    use generics                                                                               Complex Ex
                                                                                       Creating a
                                            Odds & Sods
                                                                                      Generic Class            Multiple Type Params
                          Tips
                                                                                                      Other Types
                Subsystem                                       Java Generics:
                Frameworks                                                                                        Simple Ex
                                                                 a Deep Dive
                                      Creating a                                            Creating a
                                        Generic                                           Generic Method               Complex Ex
              Multi-tier
                                      Framework
              Frameworks
                                                                                                           PECS Reprised
                          Simple Ex
                                                  Generics in                   Recursive
                                                  Frameworks                   Generic Types
                                  GWT                                                                 Simple Ex

                                                                Guava
                                                 Spring                       Class        Enums




Bryan Basham – Java Generics: a Deep Dive                                                                                                   Slide 72
RJUG : 12-Dec-2012                                          © Copyright 2012, Software Alchemy




                                  Tips from Effective Java

      ●     Don't use raw types in new code
      ●     Eliminate unchecked warnings
                    –    Removed raw types
                    –    Or suppress
      ●     Prefer lists to arrays
                    –    Arrays are reified (runtime value checks);
                          whereas lists are erased (compile-time checks)
      ●     Favor generic types
                    –    Courageously create generic types and methods
Bryan Basham – Java Generics: a Deep Dive                                               Slide 73
RJUG : 12-Dec-2012                                                © Copyright 2012, Software Alchemy




                                  Tips from Effective Java

      ●     Favor generic methods
      ●     Use bounded wildcards to increase API
            flexibility
                    –    PECS principle
      ●     Consider type-safe heterogeneous containers
                    –    Example API:
      public interface Favorites {
          public <T> void putFavorite(Class<T> type, T instance);
          public <T> T getFavorite(Class<T> type);
      }




Bryan Basham – Java Generics: a Deep Dive                                                     Slide 74
RJUG : 12-Dec-2012                                       © Copyright 2012, Software Alchemy




                                  When NOT to use Generics

      ●     Don't be afraid of complex typed data
            structures, but...
      ●     Remember that primitives are stored as
            wrapped objects inside of generic collections.
      ●     Complex computations over such complex
            data structures can lead to:
                    –    Lots of unnecessary auto-boxing
                    –    Thus hinders performance
      ●     But... the first rule of optimization is ???
Bryan Basham – Java Generics: a Deep Dive                                            Slide 75
RJUG : 12-Dec-2012                                                         © Copyright 2012, Software Alchemy




                                  Example
              private void processAverages() {
                  int dayCount = 1;
                  Map<PathwayStation, Long> stationTotals =
                          new EnumMap<>(PathwayStation.class);
                  Map<PathwayStation, Map<Category, Long>> categoryTotals =
                          new EnumMap<>(PathwayStation.class);
                 // start with today's stats
                 for (PathwayStation s : PathwayStation.values()) {
                      stationTotals.put(s, dailyLoadStats.getStationTotal(s));
                      Map<Category, Long> catTotalsByStation = new HashMap<>();
                      categoryTotals.put(s, catTotalsByStation);
                      for (Category c : pathwayConfig.getCategories()) {
                          catTotalsByStation.put(c, dailyLoadStats.getCategoryTotal(s, c));
                      }
                  }
                  // process the averages
                  for (DailyLoadStatistics dls : loadStatsHistory) {
                      cayCount++;
                      // accumulate station totals
                      for (PathwayStation s : PathwayStation.values()) {
                          stationTotals.put(s, stationTotals.get(s)+dls.getStationTotal(s));
                          // accumulate category totals
                          Map<Category, Long> catTotalsByStation = categoryTotals.get(s);
                          for (Category c : pathwayConfig.getCategories()) {
                              catTotalsByStation.put(c, catTotalsByStation.get(c)
                                                        +dls.getCategoryTotal(s, c));
                          // MORE...
Bryan Basham – Java Generics: a Deep Dive                                                              Slide 76
RJUG : 12-Dec-2012                                                         © Copyright 2012, Software Alchemy




                                  Example Refactored

              private void processAverages() {
                  int dayCount = 1;
                  List<Category> categories = pathwayConfig.getCategories();
                  long[] stationTotals = new long[PathwayStation.values().length];
                  long[][] categoryTotals = new long[PathwayStation.values().length][];
                  // start with today's stats
                  for (PathwayStation s : PathwayStation.values()) {
                      stationTotals[s.ordinal()] = dailyLoadStats.getStationTotal(s);
                      // categories
                      long[] catTotalsByStation = new long[categories.size()];
                      categoryTotals[s.ordinal()] = catTotalsByStation;
                      int cc = 0;
                      for (Category c : pathwayConfig.getCategories()) {
                          catTotalsByStation[cc++] = dailyLoadStats.getCategoryTotal(s, c);
                      }
                  }
                  // process the averages
                  for (DailyLoadStatistics dls : loadStatsHistory) {
                      dayCount++;
                      // accumulate station totals
                      for (PathwayStation s : PathwayStation.values()) {
                          stationTotals[s.ordinal()] += dls.getStationTotal(s);
                          // accumulate category totals
                          // MORE... you get the idea


Bryan Basham – Java Generics: a Deep Dive                                                              Slide 77
RJUG : 12-Dec-2012                             © Copyright 2012, Software Alchemy




                                  Reflection

      ●     Because generic type arguments are erased at
            runtime, you cannot perform reflection on an
            object instance.
      ●     However, you can perform reflection on the
            type parameters of generic classes and
            methods.




Bryan Basham – Java Generics: a Deep Dive                                  Slide 78
RJUG : 12-Dec-2012                                                © Copyright 2012, Software Alchemy




                                  Reflection Example

      class GenericClass<T extends Enum<T>, N extends Number> { }

      public class ReflectionTest {
          @Test
          public void test1() {
              Class<?> clazz = GenericClass.class;
              TypeVariable<?>[] typeParams = clazz.getTypeParameters();
              // test type params
              TypeVariable<?> first = typeParams[0];
              assertEquals("T", first.getName());
              Type firstBoundsType = first.getBounds()[0];
              assertTrue("first param type is bound by a parameterized type",
                      (firstBoundsType instanceof ParameterizedType));
              assertEquals(Enum.class,
                      ((ParameterizedType)firstBoundsType).getRawType());
              TypeVariable<?> second = typeParams[1];
              assertEquals("N", second.getName());
              Type secondBoundsType = second.getBounds()[0];
              assertTrue("second param type is bound by a standard type",
                      !(secondBoundsType instanceof ParameterizedType));
              assertEquals(Number.class, secondBoundsType);
          }
      }
Bryan Basham – Java Generics: a Deep Dive                                                     Slide 79
RJUG : 12-Dec-2012                                                                                              © Copyright 2012, Software Alchemy




                                  Q&A
                                                                  Erasure       Wildcards & PECS
                                                      History
                                                                                      Mixing w/
                                                                                      Raw Types
                                       Reflection                   History
                                                                                                   Simple Ex
                                                                   & Theory
                    When not to
                    use generics                                                                               Complex Ex
                                                                                       Creating a
                                            Odds & Sods
                                                                                      Generic Class            Multiple Type Params
                           Tips
                                                                                                      Other Types
                Subsystem                                       Java Generics:
                Frameworks                                                                                        Simple Ex
                                                                 a Deep Dive
                                       Creating a                                           Creating a
                                         Generic                                          Generic Method               Complex Ex
              Multi-tier
                                       Framework
              Frameworks
                                                                                                           PECS Reprised
                          Simple Ex
                                                  Generics in                   Recursive
                                                  Frameworks                   Generic Types
                                  GWT                                                                 Simple Ex

                                                                Guava
                                                 Spring                       Class        Enums




Bryan Basham – Java Generics: a Deep Dive                                                                                                   Slide 80
RJUG : 12-Dec-2012                                                  © Copyright 2012, Software Alchemy




                                  Resources
      ●     Wikipedia
      ●     Official Java Tutorial
      ●     Generics in the Java Programming Language (tutorial by Gilad Bracha)
      ●     Angelika Langer's Java Generics FAQ
      ●     JSR 14: Add Generic Types to the Java Programming Language
      ●     Book: Java Generics (O'Reilly Media)
      ●     More Wikipedia:
                    –    Type Systems
                    –    Generic Programming
      ●     StackOverflow on PECS principle



Bryan Basham – Java Generics: a Deep Dive                                                       Slide 81

Java Generics: a deep dive

  • 1.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Java Generics History & Theory Creating a Odds & Sods Generic Class Java Generics: a Deep Dive Creating a Creating a Generic Generic Method Framework Generics in Recursive Frameworks Generic Types Bryan Basham Software Alchemy basham47@gmail.com http://www.linkedin.com/in/SoftwareAlchemist Bryan Basham – Java Generics: a Deep Dive Slide 1
  • 2.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy History & Theory Erasure Wildcards & PECS History Mixing w/ Raw Types History & Theory Creating a Odds & Sods Generic Class Java Generics: a Deep Dive Creating a Creating a Generic Generic Method Framework Generics in Recursive Frameworks Generic Types Bryan Basham – Java Generics: a Deep Dive Slide 2
  • 3.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Why Are Generics Important? ● The great debate of dynamic vs static languages – Dynamic is great for rapid prototyping – Static is better for serious engineering – I love both, but... ● This talk is about serious engineering, so... – Let the compiler catch more potential bugs – Apply more rigor to your designs – Add more flexibility to your designs Bryan Basham – Java Generics: a Deep Dive Slide 3
  • 4.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy History ● Generic types were introduced in J2SE 5.0 in 2004 – Additional type safety – Reduced the need for casting ● Pre-generics code example: List v = new ArrayList(); v.add(“test”); Integer i = (Integer) v.get(0); // Run-time error ● Post-generics: List<String> v = new ArrayList<String>(); v.add(“test”); Integer i = v.get(0); // Compile-time error Bryan Basham – Java Generics: a Deep Dive Slide 4
  • 5.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Theory ● Unlike C++ templates – Primitives cannot be type parameters List<int> numbers; // not legal – Only one generated code file ● Generics are a compile-time feature – At run-time type variables (eg T) become Object – This is called erasure public class LispList<T> { public class LispList { private T item; private Object item; private LispList<T> next; private LispList next; public T first() {...} public Object first() {...} // etc... // etc... } } Bryan Basham – Java Generics: a Deep Dive Slide 5
  • 6.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Terminology Type Parameter ● Generic type: public class LispList<T> { ... } public class Pair<T1, T2> { ... } Type Argument ● Parameterized type: (required in Java 5 & 6) LispList<String> list = new LispList<String>("first"); Pair<String,Integer> p1 = new Pair<String,Integer>("random number", 47); ● Type inference in Java 7: Pair<String,Integer> p1 = new Pair<>("random number", 47); Map<FrequencyCategory, “the diamond” Map<RecencyCategory, EnumMap<RfmAnalysisStatistic, Number>>> rfmContent = new HashMap<>(); Bryan Basham – Java Generics: a Deep Dive Slide 6
  • 7.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy More Terminology Wildcard Argument ● Generic method: (unbounded) public void printPair(Pair<?,?> p) { System.out.println("(" + p.getFirst() + "," + p.getSecond() + ")"); } Upper-Bound Wildcard ● Bounded wildcards: public interface DomainEntityDAO<T extends DomainEntity> { public long create(T entity); public T findById(long id); } Generic Method Type Parameter Lower-Bound Wildcard public static <T> void flush(Collection<T> coll, Sink<? super T> sink) { // flush all elements in the collection to the sink } Bryan Basham – Java Generics: a Deep Dive Slide 7
  • 8.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy The PECS Principle ● Producers use extends: public T something() { /* this method produces a T or subclasses */ } ● Consumers use super: public void something(T) { /* this method consumes a T or ancestors */ } ● So what? The collection produces elements to compare to find the max. // from the java.util.Collections API: public static <T> T max(Collection<? extends T> collection, Comparator<? super T> comparator) The comparator consumes elements ● More explanation: click here while performing the comparison. Bryan Basham – Java Generics: a Deep Dive Slide 8
  • 9.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Mixing Raw Types with Generics ● A raw type is a use of a generic type without type arguments: Raw Type List<String> list1 = new ArrayList();// legal, but with warnings list1.add("abc"); list1.add(47); // not legal – Compiler treats this as a list of strings (only); the type info is on the variable not the RT object @SuppressWarnings("rawtypes") // use this to suppress warnings List<?> list3 = new ArrayList(); list3.add("abc"); // not legal list3.add(47); // not legal list3.add(null); // null is the only legal value – Compiler treats this as a list of unknown values Bryan Basham – Java Generics: a Deep Dive Slide 9
  • 10.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Mixing Raw Types with Generics ● More examples: List list5 = new ArrayList<String>(); list5.add("abc"); // legal list5.add(47); // legal, but not type-safe – Compiler treats this as a list of anything List list6 = new ArrayList<?>(); // compiler error – Not legal to use wildcards in instantiation syntax ● Don't mix raw types with generic types – Unless integrating with legacy APIs – NEVER use raw types in new code Bryan Basham – Java Generics: a Deep Dive Slide 10
  • 11.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Creating a Generic Class Erasure Wildcards & PECS History Mixing w/ Raw Types History Simple Ex & Theory Complex Ex Creating a Odds & Sods Generic Class Multiple Type Params Other Types Java Generics: a Deep Dive Creating a Creating a Generic Generic Method Framework Generics in Recursive Frameworks Generic Types Bryan Basham – Java Generics: a Deep Dive Slide 11
  • 12.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A Simple Example ● A class with one type parameter: public class Optional<T> { private final T item; public Optional(T item) { this.item = item; } public boolean isPresent() { return item != null; } public T or(T defaultValue) { return item != null ? item : defaultValue; } public T get() { if (item != null) { return item; } else { throw new IllegalStateException(); } } } Bryan Basham – Java Generics: a Deep Dive Slide 12
  • 13.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A Simple Example: Unit Tests ● A class with one type parameter: @Test public void test() { Integer item = null; Optional<Integer> opt = new Optional<Integer>(item); assertTrue(!opt.isPresent()); assertEquals(47, opt.or(47).intValue()); try { int value = opt.get(); fail(); } catch (IllegalStateException e) { /* succeeds */ } item = 42; opt = new Optional<Integer>(item); assertTrue(opt.isPresent()); assertEquals(42, opt.or(47).intValue()); assertEquals(42, opt.get().intValue()); } ● BTW, this is a hack of a real Guava class Bryan Basham – Java Generics: a Deep Dive Slide 13
  • 14.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Example: Classic link list ● A LISP-like linked list implementation: public class LispList<T> { private final T head; private LispList<T> tail; public LispList(T head) { this.head = head; } public T first() { return head; } public LispList<T> rest() { return tail; } public LispList<T> addToFront(T item) { LispList<T> newHead = new LispList<T>(item); newHead.tail = this; return newHead; } } Bryan Basham – Java Generics: a Deep Dive Slide 14
  • 15.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Example: Classic link list ● Simple usage test: @Test public void testAdd() { LispList<String> list = new LispList<String>("first"); list = list.addToFront("second"); list = list.addToFront("third"); list = list.addToFront("fourth"); // test the link chain assertEquals("fourth", list.first()); // car assertEquals("third", list.rest().first()); // cadr assertEquals("second", list.rest().rest().first()); // caddr assertEquals("first", list.rest().rest().rest().first()); } Bryan Basham – Java Generics: a Deep Dive Slide 15
  • 16.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Example: Classic link list ● Use generic interfaces to extend behavior: public class LispList<T> implements Iterable<T> { // skip previous code @Override public Iterator<T> iterator() { return new LispListIterator<T>(this); } private static class LispListIterator<T> implements Iterator<T> { private LispList<T> currentHead; private LispListIterator(LispList<T> listHead) { currentHead = listHead; } @Override public boolean hasNext() { return currentHead != null; } @Override public T next() { T item = currentHead.head; currentHead = currentHead.tail; return item; } @Override public void remove() { throw new UnsupportedOperationException(); } } } Bryan Basham – Java Generics: a Deep Dive Slide 16
  • 17.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Example: Classic link list ● Test the iterable behavior: @Test public void testAdd() { LispList<Integer> list = new LispList<Integer>(0); list.addToEnd(1); list.addToEnd(2); list.addToEnd(3); You can use any Iterable as the // target of a for-each statement. int count = 0; for (int value : list) { assertEquals(count++, value); } } Bryan Basham – Java Generics: a Deep Dive Slide 17
  • 18.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Using Multiple Type Params ● A class with two type parameters: public class Pair<T1, T2> { private final T1 first; private final T2 second; public Pair(T1 o1, T2 o2) { this.first = o1; this.second = o2; } public T1 getFirst() { return first; } public T2 getSecond() { return second; } } Bryan Basham – Java Generics: a Deep Dive Slide 18
  • 19.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Using Multiple Type Args ● Unit test for our Pair class: @Test public void test1() { Pair<String, Long> p1 = new Pair<String, Long>("a test", 47L); assertEquals("a test", p1.getFirst()); assertEquals(new Long(47), p1.getSecond()); // Java 7 Pair<String, Long> p2 = new Pair<>("life & everything", 42L); assertEquals("life & everything", p2.getFirst()); assertEquals(new Long(42), p2.getSecond()); } Bryan Basham – Java Generics: a Deep Dive Slide 19
  • 20.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Generic Interfaces ● A generic function to determine the truth of some condition: public interface Predicate<T> { public boolean apply(T input); } private static final Predicate<Integer> IS_EVEN_P = new Predicate<>() { public boolean apply(Integer input) { return input % 2 == 0; } }; ● A generic function to transform an input from one value to another: public interface Function<FROM, TO> { public TO apply(FROM input); } ● BTW, these are also part of Guava; one of my favorite Java libraries Bryan Basham – Java Generics: a Deep Dive Slide 20
  • 21.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Predicate Unit Test @Test public void predicateTest() { List<AppParameter> parameters = new ArrayList<>(); parameters.add(p1 = new AppParameter(PARAM1, VALUE1)); parameters.add(p2 = new AppParameter(PARAM2, VALUE2)); parameters.add(p3 = new AppParameter(PARAM3, VALUE3)); // change a few values p1.setValue(NEW_VALUE1); p2.setValue(NEW_VALUE2); // test the "is dirty" function Collection<AppParameter> dirtyList = CollectionUtils.gather(parameters, new Predicate<>() { @Override public boolean apply(AppParameter input) { return input.isDirty(); }; }); assertEquals(2, dirtyList.size()); } Bryan Basham – Java Generics: a Deep Dive Slide 21
  • 22.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Other Generic Types ● These types can be made generic... – Classes – Interfaces – Inner classes, etc ● These Java types may not be generic: – Anonymous inner classes – Exceptions – Enums Bryan Basham – Java Generics: a Deep Dive Slide 22
  • 23.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Creating a Generic Method Erasure Wildcards & PECS History Mixing w/ Raw Types History Simple Ex & Theory Complex Ex Creating a Odds & Sods Generic Class Multiple Type Params Other Types Java Generics: Simple Ex a Deep Dive Creating a Creating a Generic Generic Method Complex Ex Framework PECS Reprised Generics in Recursive Frameworks Generic Types Bryan Basham – Java Generics: a Deep Dive Slide 23
  • 24.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Why Generic Methods? ● Generic methods allow you to create algorithms that apply to a wide variety of types. ● For example, how many sorting algorithms do you need? – Sort a list of integers – Sort a list of dates – Sort a list of strings ● What do these all have in common? Bryan Basham – Java Generics: a Deep Dive Slide 24
  • 25.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A Simple Generic Method ● Gather all items in a collection that satisfy the given predicate: public static <T> Collection<T> gather(final Iterable<T> collection, final Predicate<T> predicate) { checkNotNull(collection, "collection must not be null"); checkNotNull(predicate, "predicate must not be null"); Collection<T> result = new ArrayList<T>(); for (T item : collection) { if (predicate.apply(item)) { result.add(item); } } return result; } Bryan Basham – Java Generics: a Deep Dive Slide 25
  • 26.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A gather Method Unit Test @Test public void testGather() { // Gather negative numbers Collection<Integer> test1 = CollectionUtils.gather(Arrays.asList(TEST_NUMS), IS_NEG); assertEquals(test1.size(), NEG_NUMBERS_ARRAY.length); for (Integer n : NEG_NUMBERS_ARRAY) { assertTrue("elements are correct", test1.contains(n)); } } private static final Integer[] TEST_NUMS = { -42, 42, 0, 13, -47, 42, 42, 47 }; private static final Integer[] NEG_NUMBERS_ARRAY = { -42, -47 }; private static final Predicate<Integer> IS_NEG = new Predicate<>() { public boolean apply(Integer input) { return input < 0; } }; Does anyone see the bug in this code? Bryan Basham – Java Generics: a Deep Dive Slide 26
  • 27.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A More Complex Example ● A mapping operation: public static <F, T> Collection<T> map( final Collection<F> collection, final Function<F, T> transformer) { checkNotNull(collection, "collection must not be null"); checkNotNull(transformer, "transformer must not be null"); Collection<T> result = new ArrayList<T>(); for (F item : collection) { result.add(transformer.apply(item)); } return result; } Bryan Basham – Java Generics: a Deep Dive Slide 27
  • 28.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A More Complex Example @Test public void testMap() { // Square all of the test numbers Collection<Integer> test1 = CollectionUtils.map(TEST_NUMBERS, SQUARE); assertEquals(test1.size(), TEST_NUMBERS.size()); Iterator<Integer> numbers = TEST_NUMBERS.iterator(); Iterator<Integer> squares = test1.iterator(); while (numbers.hasNext()) { int n = numbers.next().intValue(); int square = squares.next().intValue(); assertEquals("elements are correct", n * n, square); } } private static final Function<Integer, Integer> SQUARE = new Function<Integer, Integer>() { public Integer apply(Integer x) { return x * x; } }; The compiler requires type arguments for anonymous inner classes; that was the bug two slides ago. Bryan Basham – Java Generics: a Deep Dive Slide 28
  • 29.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy PECS Reprised ● So... what about that sorting problem? Can we create a single algorithm for all of these (and more)? – Sort a list of integers – Sort a list of dates – Sort a list of strings ● What do these all have in common? ● How does this relate to the Producer-extends, Consumer-super principle? Bryan Basham – Java Generics: a Deep Dive Slide 29
  • 30.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy And now the answer... ● Sorting requires that the objects in the collection are “comparable” to each other: public static <T extends Comparable<? super T>> void sort( List<T> list) { Object[] a = list.toArray(); Arrays.sort(a); ListIterator<T> i = list.listIterator(); for (int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); } } ● ...of course, this algorithm is kind-of cheating because it really sorts an array of Objects and that method uses casts to Comparable. Bryan Basham – Java Generics: a Deep Dive Slide 30
  • 31.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Recursive Generic Types Erasure Wildcards History Mixing w/ Raw Types History Simple Ex & Theory Complex Ex Creating a Odds & Sods Generic Class Multiple Type Params Other Types Java Generics: Simple Ex a Deep Dive Creating a Creating a Generic Generic Method Complex Ex Framework PECS Reprised Generics in Recursive Frameworks Generic Types Simple Ex Enums Class Bryan Basham – Java Generics: a Deep Dive Slide 31
  • 32.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Recursive Generic Types ● “A recursive generic type is any type that makes use of a generic type that has a type argument that refers to the original type.” (me) ● This is not part of the formal definition of Java generics, but I find the concept useful. – Because they pop-up every so often – And cause problems if you don't handle them correctly Bryan Basham – Java Generics: a Deep Dive Slide 32
  • 33.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A Quasi-Recursive Generic ● The Comparable interface forms a quasi- recursive generic. For example: public class RevenueBand implements Comparable<RevenueBand> { private String name; private int lowerBound; private int upperBound; @Override public int compareTo(RevenueBand that) { return this.lowerBound – that.lowerBound; } } revBand1 = new RevenueBand("<$1M", 0, 1_000_000); revBand2 = new RevenueBand("$1M - $10M", 1_000_000, 10_000_000); revBand3 = new RevenueBand("$10M - $50M", 10_000_000, 50_000_000); assertTrue(revBand1.compareTo(revBand2) < 0); Bryan Basham – Java Generics: a Deep Dive Slide 33
  • 34.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Enums ● Java enums are special types that always extend Enum, which is defined as: public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable { ... } ● This recursive definition guarantees that no enum class may extend any other class. – Of course, the compiler guarantees that because the extends (subclass clause) cannot be used in an enum definition: public enum Enum { A, B, C } Bryan Basham – Java Generics: a Deep Dive Slide 34
  • 35.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Using Enums in Generic Methods ● The generics idiom T extends Enum<T> is used frequently in code involving enums: public static <T extends Enum<T>> Function<String, T> valueOfFunct( final Class<T> enumClass) { return new Function<String, T>() { public T apply(String value) { return Enum.valueOf(enumClass, value); } }; } enum MyEnum { A, B, C } @Test public void test() { Function<String, MyEnum> myFunc = valueOfFunct(MyEnum.class); assertEquals(MyEnum.B, myFunc.apply("B")); } ● Notice the use of the enumClass argument... Bryan Basham – Java Generics: a Deep Dive Slide 35
  • 36.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy The Class Class ● The ultimate recursive generic type is Class. ● From the compiler's perspective: – MyClass.class instanceof Class<MyClass> ● Of course at run-time: – MyClass.class instanceof Class ● ...and as you just saw classes are frequently used to “identify” a type parameter on a generic method Bryan Basham – Java Generics: a Deep Dive Slide 36
  • 37.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Generics in Frameworks Erasure Wildcards & PECS History Mixing w/ Raw Types History Simple Ex & Theory Complex Ex Creating a Odds & Sods Generic Class Multiple Type Params Other Types Java Generics: Simple Ex a Deep Dive Creating a Creating a Generic Generic Method Complex Ex Framework PECS Reprised Generics in Recursive Frameworks Generic Types GWT Simple Ex Guava Spring Class Enums Bryan Basham – Java Generics: a Deep Dive Slide 37
  • 38.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Libraries to Consider ● Guava – Google's answer to Apache Commons ● Spring – The ubiquitous, light-weight, enterprise framework for Java (Java EE replacement) ● Google Web Toolkit – Modern Java-to-JavaScript bridge framework for building advanced, single-page Web GUIs Bryan Basham – Java Generics: a Deep Dive Slide 38
  • 39.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy The Guava Library Bryan Basham – Java Generics: a Deep Dive Slide 39
  • 40.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Guava Fundamentals ● Optional: holds an optional value ● Predicate: an interface for a query function ● Function: an interface for a generic mapping operation – Here's a neat little higher-order operation: public static <A, B, C> Function<A, C> compose( final Function<B, C> g, final Function<A, B> f) { return new Function<A, C>() { public C apply(A a) { return g.apply(f.apply(a)); } }; } Bryan Basham – Java Generics: a Deep Dive Slide 40
  • 41.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Function Composition Unit Test enum MyEnum { A, B, C } @Test public void test() { Function<String, MyEnum> myEnumFunc = Enums.valueOfFunction(MyEnum.class); Function<String, String> upperCaseFunc = new Function<String, String>() { public String apply(String s) { return s.toUpperCase(); } }; Function<String, MyEnum> cleanEnumFunc = Functions.compose(myEnumFunc, upperCaseFunc); assertEquals(MyEnum.B, cleanEnumFunc.apply("b")); } Bryan Basham – Java Generics: a Deep Dive Slide 41
  • 42.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Guava Collections ● Range<C extends Comparable> – A range (or "interval") defines the boundaries around a contiguous span of values of some Comparable type; for example, "integers from 1 to 100 inclusive." ● Multiset<T> – A collection that supports order-independent equality, like Set, but may have duplicate elements. ● Multimap<K,V> – A collection that maps keys to values, similar to Map, but in which each key may be associated with multiple values. ● BiMap<K,V> – A bimap (or "bidirectional map") is a map that preserves the uniqueness of its values as well as that of its keys. Bryan Basham – Java Generics: a Deep Dive Slide 42
  • 43.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Guava Collections ● Collections2 – transform(Collection<F>, Function<? super F, T> function) : Collection<T> : creates a new collection of transformed elements – filter(Collection<T>, Predicate<T> function) : Collection<T> : creates a new collection of selected elements – And a few more... Bryan Basham – Java Generics: a Deep Dive Slide 43
  • 44.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Guava Collections ● Iterables – boolean all(Collection<T> c, Predicate<T> predicate) : queries whether all elements satisfy the predicate – boolean any(Collection<T> c, Predicate<T> predicate) : queries whether any element satisfies the predicate – T find(Collection<T> c, Predicate<T> predicate, T defValue) : finds the first value that satisfies the predicate, or returns the default – Optional<T> tryFind(Collection<T> c, Predicate<T> predicate) : optionally finds the first value that satisfies the predicate – Lots more... Bryan Basham – Java Generics: a Deep Dive Slide 44
  • 45.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Guava Caching ● Simple API to provide in-memory caching ● Cache<K,V>: is a cache of keys to values ● CacheLoader<K,V>: is a mechanism to load cache values ● Use a CacheBuilder to construct and configure a cache Bryan Basham – Java Generics: a Deep Dive Slide 45
  • 46.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Guava Caching Example private Cache<String, WarehouseHealth> pwhHealthCache; @PostConstruct private void initializeService() { int ttlInSeconds = SpringPropertyUtils.getIntProperty( PWH_HEALTH_CACHE_TTL, DEFAULT_PWH_HEALTH_CACHE_TTL); pwhHealthCache = CacheBuilder.newBuilder() .expireAfterWrite(ttlInSeconds, TimeUnit.SECONDS) .build(new CacheLoader<String, WarehouseHealth>() { @Override public WarehouseHealth load(final String key) { List<ChannelHealth> channels = pwhPrimaryDAO.getChannelHealth(); List<String> disabledProducts = pwhPrimaryDAO.getDisabledContentSets(); boolean isFileWatcherRunning = pwhPrimaryDAO.isFileWatcherRunning(); return new WarehouseHealth(channels, disabledProducts, isFileWatcherRunning); } }); } Bryan Basham – Java Generics: a Deep Dive Slide 46
  • 47.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy The Spring Library Bryan Basham – Java Generics: a Deep Dive Slide 47
  • 48.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Spring's Context and Bean Ops ● ApplicationContext and BeanFactory – T getBean(String beanName, Class<T> requiredType) : retrieves a Spring declared bean (creates it if necessary) ● BeanUtils – T instantiate(Class<T> clazz) : creates a new instance of the bean using the no-arg constructor – T instantiateClass(Constructor<T> clazz, Object... args) : creates a new instance of a bean with a specified constructor and arguments Bryan Basham – Java Generics: a Deep Dive Slide 48
  • 49.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Spring's JdbcTemplate ● If you are not using an ORM tool like Hibernate or JPA, you should use Spring's JDBC template API – Removes boilerplate JDBC code – Converts SQLException into more useful, but silent exceptions – Allows you to focus on the SQL and data conversion – RowMapper<T> is used to convert a single ResultSet row into some Java object Bryan Basham – Java Generics: a Deep Dive Slide 49
  • 50.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Spring's JdbcTemplate ● General Queries – List<T> query(String sql, Object[] args, RowMapper<T> mapper) – T query(String sql, Object[] args, ResultSetExtractor<T> rse) ● Single Result Queries – T queryForObject(String sql, Object[] args, Class<T> clazz) – T queryForObject(String sql, Object[] args, RowMapper<T> mapper) ● Multiple Result Queries – List<T> queryForList(String sql, Object[] args, Class<T> elementType) Bryan Basham – Java Generics: a Deep Dive Slide 50
  • 51.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy JdbcTemplate Example public NovusNodeHealth getNovusHealth() { return getJdbcTemplate().queryForObject( NOVUS_HEALTH_QUERY, novusHealthMapper); } private static final String NOVUS_HEALTH_QUERY = "SELECT novus_status, dm_load_key FROM etl_promote_status WHERE" + " dm_load_key in (SELECT max(dm_load_key) FROM etl_promote_status)"; private final RowMapper<NovusNodeHealth> novusHealthMapper = new RowMapper<NovusNodeHealth>() { public NovusNodeHealth mapRow(final ResultSet rs, final int rowNum) throws SQLException { Integer loadKey = rs.getInt("dm_load_key"); String status = rs.getString("novus_status"); return new NovusNodeHealth(status, loadKey, "NOVUS"); } }; Bryan Basham – Java Generics: a Deep Dive Slide 51
  • 52.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy The GWT Library Bryan Basham – Java Generics: a Deep Dive Slide 52
  • 53.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy GWT RPC Mechanism Desktop Server HTTP User ........... ........... ........... «interface» PubDatamartRPCAsync +getStationHealth(boolean, AsyncCallback<PubDmNodeHealthDTO>) : void +stopPublishingNode( AsyncCallback<Void>) : void «interface» «class» PubDatamartRPC PubDatamartRPCImpl +getStationHealth(boolean) +getStationHealth(boolean) : PubDmNodeHealthDTO : PubDmNodeHealthDTO +stopPublishingNode() +stopPublishingNode() : void : void Bryan Basham – Java Generics: a Deep Dive Slide 53
  • 54.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy GWT RPC ● AsyncCallback is the heart of RPC mechanism: public interface AsyncCallback<T> { void onSuccess(T result); void onFailure(Throwable caught); } ● Usage: AsyncCallback<PublishingDmNodeHealthDTO> callback = new AsyncCallback<PublishingDmNodeHealthDTO>() { public void onSuccess(final PublishingDmNodeHealthDTO result) { pubHealthNode = result; // TODO refresh GUI } public void onFailure(Throwable exception) { // TODO handle exception } }; PublishingDatamartRPC.Util.getInstance() .getStationHealth(true, callback); Bryan Basham – Java Generics: a Deep Dive Slide 54
  • 55.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy GWT DataGrid ● DataGrid<T> – A table with headers and rows – T is the type of each row ● Column<T, C>: – A single column in the grid – T is the row type and C is the column type ● Cell<C>: – Defines how the cells in the grid are rendered – C is the column type Bryan Basham – Java Generics: a Deep Dive Slide 55
  • 56.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy GWT DataGrid Example usersGrid = new DataGrid<UserDTO>(); Column<UserDTO, String> userIdCOL = new Column<UserDTO, String>(editUserLinkCell) { public String getValue(final UserDTO row) { return row.getUserName(); } }; userNameCOL.setSortable(false); userNameCOL.setCellStyleNames("columnLeft"); usersGrid.addColumn(userNameCOL, "Username"); usersGrid.setColumnWidth(userNameCOL, USERNAME_COL_SIZE, Unit.PCT); private final Cell<String> editUserLinkCell = new AnchorTextCell() { protected void handleClick(final Context ctx, final String value) { EditUserPage.makeHistoryCommand(value).invoke(); } }; Bryan Basham – Java Generics: a Deep Dive Slide 56
  • 57.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Creating a Generic Framework Erasure Wildcards & PECS History Mixing w/ Raw Types History Simple Ex & Theory Complex Ex Creating a Odds & Sods Generic Class Multiple Type Params Other Types Subsystem Java Generics: Frameworks Simple Ex a Deep Dive Creating a Creating a Generic Generic Method Complex Ex Multi-tier Framework Frameworks PECS Reprised Simple Ex Generics in Recursive Frameworks Generic Types GWT Simple Ex Guava Spring Class Enums Bryan Basham – Java Generics: a Deep Dive Slide 57
  • 58.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Building a Generic Framework ● Frameworks appear in all applications, large and small ● Look for redundant code and find a common abstraction – Sometimes this will be an abstract superclass – Sometimes a generic class – Sometimes a generic algorithm – Sometimes a generic architectural metaphor – Sometimes a shared subsystem abstraction Bryan Basham – Java Generics: a Deep Dive Slide 58
  • 59.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Let's start small... ● Database query request/response that supports paging, sorting and filtering ● QueryRequest: provides input about the size and starting point of the page to query ● QueryResult<T>: provides a single page of data from the query ● PagedRowMapper<T>: extends Spring's RowMapper to provide the total count of the overall query Bryan Basham – Java Generics: a Deep Dive Slide 59
  • 60.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Paged Queries Framework «value object» QueryRequest pageStart : int pageSize : int «Service» retrieve(QueryRequest): «DAO» MyService QueryResponse<MyEntity> MyDAO Database T=MyEntity T=MyEntity «value object» QueryResult «helper» «entity» PagedRowMapper MyEntity totalCount : int page : List<T> Bryan Basham – Java Generics: a Deep Dive Slide 60
  • 61.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy The QueryResult Class public class QueryResult<T> implements Serializable, Iterable<T> { private final int totalCount; private final List<T> items; public QueryResult(final int totalCountIn, final List<T> itemsIn) { this.totalCount = totalCountIn; this.items = itemsIn; } public final int getTotalCount() { return this.totalCount; } public final List<T> getItems() { return this.items; } @Override public final Iterator<T> iterator() { return this.items.iterator(); } } Bryan Basham – Java Generics: a Deep Dive Slide 61
  • 62.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy The QueryResult Class public abstract class PagedRowMapper<T> implements RowMapper<T> { private Integer totalCount = null; public Integer getTotalCount() { return (this.totalCount != null) ? this.totalCount : 0; } @Override public final T mapRow(final ResultSet rs, final int rowNum) throws SQLException { if (this.totalCount == null) { this.totalCount = rs.getInt("totalCount"); } return mapEntity(rs, rowNum); } public abstract T mapEntity(ResultSet rs, int rowNum) throws SQLException; } Bryan Basham – Java Generics: a Deep Dive Slide 62
  • 63.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A Multi-tier Framework ● A simple “data entry” application can take advantage of the concept of an “Entity” (with CRUD operations) across all application tiers: «GWT» «GWT RPC» «Service» «DAO» MyGUI HTTP MyRPC MySvc MyDAO DB User «helper» MyTransformer «DTO» «JPA» MyEntityDTO MyEntity Bryan Basham – Java Generics: a Deep Dive Slide 63
  • 64.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A Multi-tier Framework T T T,ID «interface» «interface» «interface» DomainEntity DomainEntity DomainEntity RPC Service DAO +create(T):ID +findById(ID):T +update(T) +delete(T) T=User «interface» UserRPC T T T,ID=Long «class» «class» «class» AbstractDomain AbstractDomain AbstractDomain EntityRpcImpl EntityService EntityDAO T=User T=User T=User «GWT RPC» «GWT» «Service» «DAO» UserRpc DB UserPage HTTP UserSvc UserDAO Impl User «DTO» «helper» «JPA» UserDTO UserToDtoTfm User Bryan Basham – Java Generics: a Deep Dive Slide 64
  • 65.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A Multi-tier Framework: the Interfaces public interface DomainEntity { public Long getId(); public void setId(Long id); public boolean isNew(); // other metadata properties } public interface DomainEntityDAO<T extends DomainEntity, ID extends Serializable> { public ID create(T entity); public T findById(ID id); public boolean delete(T entity); public void update(T entity); } public interface DomainEntityService<T extends DomainEntity> { public EntityResponse<T> create(T entity); public EntityResponse<T> retrieveById(Long entityId); public ServerResponse update(T entity); public ServerResponse delete(Long entityId); } Bryan Basham – Java Generics: a Deep Dive Slide 65
  • 66.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy A Multi-tier Framework: the Interfaces public interface EntityDTO extends Model, IsSerializable { public static enum Depth { SURFACE, SUMMARY, TREE, DEEP }; public Long getId(); public void setId(Long id); public Depth getDepth(); public void setDepth(Depth depth); public boolean isNew(); public void merge(EntityDTO dto); } public interface DomainEntityRPC<DTO extends EntityDTO> { public abstract GuiEntityResponse<DTO> create(DTO entity); public abstract GuiEntityResponse<DTO> retrieveById(Long id); public abstract GuiServerResponse update(DTO entity); public abstract GuiServerResponse delete(Long id); } public interface DomainEntityRpcAsync<DTO extends EntityDTO> { void create(DTO entity, AsyncCallback<GuiEntityResponse<DTO>> c); void retrieveById(Long id, AsyncCallback<GuiEntityResponse<DTO>> c); void update(DTO entity, AsyncCallback<GuiServerResponse> c); void delete(Long id, AsyncCallback<GuiServerResponse> c); } Bryan Basham – Java Generics: a Deep Dive Slide 66
  • 67.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Subsystem Framework Example ● The Incentives framework supports three concrete subsystems in a financial application – Apps main function is supply chain analysis ● Sales line item data ● Plus lots of reference data: products, pricing catalogs, customers, etc – Incentives provides decision support ● SPA: special pricing catalog assignment ● Rebates: identify SLIs for rebates to resellers ● SCA: sales rep commissions Bryan Basham – Java Generics: a Deep Dive Slide 67
  • 68.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Incentives Framework Concepts Program Contains inference and calculation rules. GUI Summary Rules objects Inference rules generate associations. Incentive's Domain Metadata Association Model mind-map Calculation rules generate calculation results. Entity CalcResult Transaction Bryan Basham – Java Generics: a Deep Dive Slide 68
  • 69.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Incentives “Programs” Flow Nucleus Txn Eligibility Association<Txn,Program> Txn Assignment Association<Txn,Entity> Entity Calculation CalculationResult Entity Adjustment CalculationResult#AuditRecord Bryan Basham – Java Generics: a Deep Dive Slide 69
  • 70.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Incentives Analysis Model ProgramSummary Abstract Rebates ProgramService ProgramDAO ProgramEditor DataService DataServiceDAO ProgramTest TransactionService TransactionDAO ProgramReview EligibilityEditor Rebates Rebates ExecutionService ExecutionDAO ReRater Bryan Basham – Java Generics: a Deep Dive Slide 70
  • 71.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Incentives Execution Services «interface» Service T extends Entity «interface» IncentiveExecution «abstract» Service AbstractBaseService «abstract» T extends Entity AbstractIncentive T=ProfileEntity ExecutionService «interface» RebatesExecution Service +generatePayoutPayment +getPaymentHistory T=ProfileEntity T=SpaCatalogRecord «nucleusService» «nucleusService» RebatesExecution SpaExecution ServiceImpl ServiceImpl Bryan Basham – Java Generics: a Deep Dive Slide 71
  • 72.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Odds & Sods Erasure Wildcards & PECS History Mixing w/ Raw Types Reflection History Simple Ex & Theory When not to use generics Complex Ex Creating a Odds & Sods Generic Class Multiple Type Params Tips Other Types Subsystem Java Generics: Frameworks Simple Ex a Deep Dive Creating a Creating a Generic Generic Method Complex Ex Multi-tier Framework Frameworks PECS Reprised Simple Ex Generics in Recursive Frameworks Generic Types GWT Simple Ex Guava Spring Class Enums Bryan Basham – Java Generics: a Deep Dive Slide 72
  • 73.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Tips from Effective Java ● Don't use raw types in new code ● Eliminate unchecked warnings – Removed raw types – Or suppress ● Prefer lists to arrays – Arrays are reified (runtime value checks); whereas lists are erased (compile-time checks) ● Favor generic types – Courageously create generic types and methods Bryan Basham – Java Generics: a Deep Dive Slide 73
  • 74.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Tips from Effective Java ● Favor generic methods ● Use bounded wildcards to increase API flexibility – PECS principle ● Consider type-safe heterogeneous containers – Example API: public interface Favorites { public <T> void putFavorite(Class<T> type, T instance); public <T> T getFavorite(Class<T> type); } Bryan Basham – Java Generics: a Deep Dive Slide 74
  • 75.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy When NOT to use Generics ● Don't be afraid of complex typed data structures, but... ● Remember that primitives are stored as wrapped objects inside of generic collections. ● Complex computations over such complex data structures can lead to: – Lots of unnecessary auto-boxing – Thus hinders performance ● But... the first rule of optimization is ??? Bryan Basham – Java Generics: a Deep Dive Slide 75
  • 76.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Example private void processAverages() { int dayCount = 1; Map<PathwayStation, Long> stationTotals = new EnumMap<>(PathwayStation.class); Map<PathwayStation, Map<Category, Long>> categoryTotals = new EnumMap<>(PathwayStation.class); // start with today's stats for (PathwayStation s : PathwayStation.values()) { stationTotals.put(s, dailyLoadStats.getStationTotal(s)); Map<Category, Long> catTotalsByStation = new HashMap<>(); categoryTotals.put(s, catTotalsByStation); for (Category c : pathwayConfig.getCategories()) { catTotalsByStation.put(c, dailyLoadStats.getCategoryTotal(s, c)); } } // process the averages for (DailyLoadStatistics dls : loadStatsHistory) { cayCount++; // accumulate station totals for (PathwayStation s : PathwayStation.values()) { stationTotals.put(s, stationTotals.get(s)+dls.getStationTotal(s)); // accumulate category totals Map<Category, Long> catTotalsByStation = categoryTotals.get(s); for (Category c : pathwayConfig.getCategories()) { catTotalsByStation.put(c, catTotalsByStation.get(c) +dls.getCategoryTotal(s, c)); // MORE... Bryan Basham – Java Generics: a Deep Dive Slide 76
  • 77.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Example Refactored private void processAverages() { int dayCount = 1; List<Category> categories = pathwayConfig.getCategories(); long[] stationTotals = new long[PathwayStation.values().length]; long[][] categoryTotals = new long[PathwayStation.values().length][]; // start with today's stats for (PathwayStation s : PathwayStation.values()) { stationTotals[s.ordinal()] = dailyLoadStats.getStationTotal(s); // categories long[] catTotalsByStation = new long[categories.size()]; categoryTotals[s.ordinal()] = catTotalsByStation; int cc = 0; for (Category c : pathwayConfig.getCategories()) { catTotalsByStation[cc++] = dailyLoadStats.getCategoryTotal(s, c); } } // process the averages for (DailyLoadStatistics dls : loadStatsHistory) { dayCount++; // accumulate station totals for (PathwayStation s : PathwayStation.values()) { stationTotals[s.ordinal()] += dls.getStationTotal(s); // accumulate category totals // MORE... you get the idea Bryan Basham – Java Generics: a Deep Dive Slide 77
  • 78.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Reflection ● Because generic type arguments are erased at runtime, you cannot perform reflection on an object instance. ● However, you can perform reflection on the type parameters of generic classes and methods. Bryan Basham – Java Generics: a Deep Dive Slide 78
  • 79.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Reflection Example class GenericClass<T extends Enum<T>, N extends Number> { } public class ReflectionTest { @Test public void test1() { Class<?> clazz = GenericClass.class; TypeVariable<?>[] typeParams = clazz.getTypeParameters(); // test type params TypeVariable<?> first = typeParams[0]; assertEquals("T", first.getName()); Type firstBoundsType = first.getBounds()[0]; assertTrue("first param type is bound by a parameterized type", (firstBoundsType instanceof ParameterizedType)); assertEquals(Enum.class, ((ParameterizedType)firstBoundsType).getRawType()); TypeVariable<?> second = typeParams[1]; assertEquals("N", second.getName()); Type secondBoundsType = second.getBounds()[0]; assertTrue("second param type is bound by a standard type", !(secondBoundsType instanceof ParameterizedType)); assertEquals(Number.class, secondBoundsType); } } Bryan Basham – Java Generics: a Deep Dive Slide 79
  • 80.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Q&A Erasure Wildcards & PECS History Mixing w/ Raw Types Reflection History Simple Ex & Theory When not to use generics Complex Ex Creating a Odds & Sods Generic Class Multiple Type Params Tips Other Types Subsystem Java Generics: Frameworks Simple Ex a Deep Dive Creating a Creating a Generic Generic Method Complex Ex Multi-tier Framework Frameworks PECS Reprised Simple Ex Generics in Recursive Frameworks Generic Types GWT Simple Ex Guava Spring Class Enums Bryan Basham – Java Generics: a Deep Dive Slide 80
  • 81.
    RJUG : 12-Dec-2012 © Copyright 2012, Software Alchemy Resources ● Wikipedia ● Official Java Tutorial ● Generics in the Java Programming Language (tutorial by Gilad Bracha) ● Angelika Langer's Java Generics FAQ ● JSR 14: Add Generic Types to the Java Programming Language ● Book: Java Generics (O'Reilly Media) ● More Wikipedia: – Type Systems – Generic Programming ● StackOverflow on PECS principle Bryan Basham – Java Generics: a Deep Dive Slide 81