Even after a few years writing principally in Java, I struggle to master the finer points of this topic. Here's an example to help.
This example has nothing really to do with hash maps or logging; those are just an excuse I chose and the example is derived from something real I was doing a few days ago. Now I've come back to take permanent notes for next time.
Let's imagine you're rendering several POJOs as hash maps to log their contents. You accumulate them as one or more later to write to a log for use by front-line customer support guys. You don't want to write myriad logging intake methods like...
logPerson( Person pojo )
logPlace( Place pojo )
logThing( Thing pojo )
...because ten months from now you'll be back needing to add one more POJO to the mix.
Instead, what you want is just to write one method, here logPojo(). So, do the following. I forget whether to insert the magic in front of the method return type or after; I have to remember to use the T both there, and again as the type of argument pojo. I wrote this note to help me remember that.
package com.etretatlogiciels.pojo; import java.util.HashMap; import java.util.Map; import com.etretatlogiciels.pojo.PojoInterface; public class PojoLogging { private Map< String, String > loggedPojos = new HashMap< String, String >(); ... public static < T extends PojoInterface > void logPojo( T pojo ) { accumulatePojos( pojo.toHashMap() ); } ... private static void accumulatePojos( Map< String, String > map ) { PojoLogging log = PojoLogging.getInstance(); if( log.loggedPojos == null ) log.loggedPojos = map; else log.loggedPojos.putAll( map ); } }
The most important part of the magic is accomplished by getting each POJO to implement the following interface:
package com.etretatlogiciels.pojo; import java.util.Map; public interface PojoInterface { public Map< String, String > toHashMap(); }
Here's one of the POJOs:
package com.etretatlogiciels.pojo; import java.io.Serializable; public class Person implements Serializable, PojoInterface { private String name; ...
Then, let's say you need to log not one, but a list of POJOs at some point. You'd have to add these methods...
logPersonList( List< Person > pojo )
logPlaceList( List< Place > pojo )
logThingList( List< Thing > pojo )
...and implement them to boot.
Instead, to continue a theme, you'd just insert this next method into PojoLogging above:
import java.util.List; ... public static < T extends PojoInterface > void logPojoList( int which, List< T > pojoList ) { int i = 1; for( PojoInterface pojo : pojoList ) { String string = pojo.toString(); Map< String, String > map = new HashMap< String, String >( 1 ); map.put( i+"", string ); accumulatePojos( map ); i++; } } ...
* POJO: "plain, old Java object," i.e.: a class expressing a very simple data object, sometimes also called a bean.