SlideShare a Scribd company logo
1 of 81
Download to read offline
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

More Related Content

What's hot

jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentation
John Slick
 

What's hot (20)

JDBC – Java Database Connectivity
JDBC – Java Database ConnectivityJDBC – Java Database Connectivity
JDBC – Java Database Connectivity
 
Jsp ppt
Jsp pptJsp ppt
Jsp ppt
 
Java: GUI
Java: GUIJava: GUI
Java: GUI
 
Jdbc Ppt
Jdbc PptJdbc Ppt
Jdbc Ppt
 
jpa-hibernate-presentation
jpa-hibernate-presentationjpa-hibernate-presentation
jpa-hibernate-presentation
 
JUnit Presentation
JUnit PresentationJUnit Presentation
JUnit Presentation
 
Io streams
Io streamsIo streams
Io streams
 
Java - Generic programming
Java - Generic programmingJava - Generic programming
Java - Generic programming
 
Introduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examplesIntroduction to JPA and Hibernate including examples
Introduction to JPA and Hibernate including examples
 
Java Networking
Java NetworkingJava Networking
Java Networking
 
Introduction to java
Introduction to java Introduction to java
Introduction to java
 
Automation Testing with KATALON Cucumber BDD
Automation Testing with KATALON Cucumber BDDAutomation Testing with KATALON Cucumber BDD
Automation Testing with KATALON Cucumber BDD
 
JDBC - JPA - Spring Data
JDBC - JPA - Spring DataJDBC - JPA - Spring Data
JDBC - JPA - Spring Data
 
Developing Complex Business Rules with Drools Integration
Developing Complex Business Rules with Drools IntegrationDeveloping Complex Business Rules with Drools Integration
Developing Complex Business Rules with Drools Integration
 
Java IO Package and Streams
Java IO Package and StreamsJava IO Package and Streams
Java IO Package and Streams
 
JPA and Hibernate
JPA and HibernateJPA and Hibernate
JPA and Hibernate
 
Delegates and events in C#
Delegates and events in C#Delegates and events in C#
Delegates and events in C#
 
Java Fundamentals
Java FundamentalsJava Fundamentals
Java Fundamentals
 
Introduction to class in java
Introduction to class in javaIntroduction to class in java
Introduction to class in java
 
C# Exceptions Handling
C# Exceptions Handling C# Exceptions Handling
C# Exceptions Handling
 

Similar to Java Generics: a deep dive

Leveraging Adobe JavaScript Virtual Machine
Leveraging Adobe JavaScript Virtual MachineLeveraging Adobe JavaScript Virtual Machine
Leveraging Adobe JavaScript Virtual Machine
Z Chen
 
Core java 5 days workshop stuff
Core java 5 days workshop stuffCore java 5 days workshop stuff
Core java 5 days workshop stuff
Rajiv Gupta
 
Profiler Instrumentation Using Metaprogramming Techniques
Profiler Instrumentation Using Metaprogramming TechniquesProfiler Instrumentation Using Metaprogramming Techniques
Profiler Instrumentation Using Metaprogramming Techniques
Ritu Arora
 

Similar to Java Generics: a deep dive (10)

0 E158 C10d01
0 E158 C10d010 E158 C10d01
0 E158 C10d01
 
0 E158 C10d01
0 E158 C10d010 E158 C10d01
0 E158 C10d01
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
 
Scan-2012-nadezhin-zhilin-jinterval
Scan-2012-nadezhin-zhilin-jintervalScan-2012-nadezhin-zhilin-jinterval
Scan-2012-nadezhin-zhilin-jinterval
 
Leveraging Adobe JavaScript Virtual Machine
Leveraging Adobe JavaScript Virtual MachineLeveraging Adobe JavaScript Virtual Machine
Leveraging Adobe JavaScript Virtual Machine
 
The Forces Driving Java
The Forces Driving JavaThe Forces Driving Java
The Forces Driving Java
 
Web Development using jQuery
Web Development using jQueryWeb Development using jQuery
Web Development using jQuery
 
Core java 5 days workshop stuff
Core java 5 days workshop stuffCore java 5 days workshop stuff
Core java 5 days workshop stuff
 
Profiler Instrumentation Using Metaprogramming Techniques
Profiler Instrumentation Using Metaprogramming TechniquesProfiler Instrumentation Using Metaprogramming Techniques
Profiler Instrumentation Using Metaprogramming Techniques
 
From data storage to information management
From data storage to information managementFrom data storage to information management
From data storage to information management
 

Recently uploaded

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 

Recently uploaded (20)

%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 

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