Upper Bounds


As mentioned, every type parameter has a default upper bound of Object. You can constrain a type parameter to a different upper bound. For example, you might want to supply an EventMap class, where the key must be bound to a Date typeeither java.util.Date or java.sql.Date (which is a subclass of java.util.Date). A simple test:

 package sis.util; import junit.framework.*; import java.util.*; public class EventMapTest extends TestCase {    public void testSingleElement() {       EventMap<java.sql.Date,String> map =          new EventMap<java.sql.Date,String>();       final java.sql.Date date =          new java.sql.Date(new java.util.Date().getTime());       final String value = "abc";       map.put(date, value);       List<String> values = map.get(date);       assertEquals(value, values.get(0));    } } 

The EventMap class itself has no different behavior, only additional constraints on the type parameter K:

 package sis.util; public class EventMap<K extends java.util.Date,V>    extends MultiHashMap<K,V> { } 

You use the extends keyword to specify the upper bound for a type parameter. In this example, the K type parameter for EventMap has an upper bound of java.util.Date. Code using an EventMap must bind the key to a java.util.Date or a subclass of java.util.Date (such as java.sql.Date). If you attempt to do otherwise:

 EventMap<String,String> map = new EventMap<String,String>(); 

you will receive compile-time errors:

 type parameter java.lang.String is not within its bound EventMap<String,String> map = new EventMap<String,String>();          ^ type parameter java.lang.String is not within its bound EventMap<String,String> map = new EventMap<String,String>();                                            ^ 

The compiler replaces naked type variables in generated code with the upper bound type. This gives you the ability to send more specific messages to naked type objects within the generic class.

You want the ability to extract all event descriptions from the EventMap for events where the date has passed. Code the following test in Event-MapTest.

 public void testGetPastEvents() {    EventMap<Date,String> events = new EventMap<Date,String>();    final Date today = new java.util.Date();    final Date yesterday =       new Date(today.getTime() - 86400000);    events.put(today, "sleep");    final String descriptionA = "birthday";    final String descriptionB = "drink";    events.put(yesterday, descriptionA);    events.put(yesterday, descriptionB);    List<String> descriptions = events.getPastEvents();    assertTrue(descriptions.contains(descriptionA));    assertTrue(descriptions.contains(descriptionB)); } 

Within EventMap, you can presume that objects of type K are Date objects:

 package sis.util; import java.util.*; public class EventMap<K extends Date,V>    extends MultiHashMap<K,V> {    public List<V> getPastEvents() {       List<V> events = new ArrayList<V>();       for (Map.Entry<K,List<V>> entry: entrySet()) {          K date = entry.getKey();          if (hasPassed(date))             events.addAll(entry.getValue());       }       return events;    }    private boolean hasPassed(K date) {       Calendar when = new GregorianCalendar();       when.setTime(date);       Calendar today = new GregorianCalendar();       if (when.get(Calendar.YEAR) != today.get(Calendar.YEAR))          return when.get(Calendar.YEAR) < today.get(Calendar.YEAR);       return when.get(Calendar.DAY_OF_YEAR) <          today.get(Calendar.DAY_OF_YEAR);    } } 

In order to accomplish this, you'll have to add a method to MultiHashMap to return the entrySet from the encapsulated map:

 protected Set<Map.Entry<K,List<V>>> entrySet() {    return map.entrySet(); } 

The entrySet method returns a set bound to the Map.Entry type. Each Map.Entry object in the Set is in turn bound to the key type (K) and a list of the value type (List<V>).



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net