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.
01.
package
com.etretatlogiciels.pojo;
02.
03.
import
java.util.HashMap;
04.
import
java.util.Map;
05.
import
com.etretatlogiciels.pojo.PojoInterface;
06.
07.
public
class
PojoLogging
08.
{
09.
private
Map< String, String > loggedPojos =
new
HashMap< String, String >();
10.
11.
...
12.
13.
public
static
< T
extends
PojoInterface >
void
logPojo( T pojo )
14.
{
15.
accumulatePojos( pojo.toHashMap() );
16.
}
17.
18.
...
19.
20.
private
static
void
accumulatePojos( Map< String, String > map )
21.
{
22.
PojoLogging log = PojoLogging.getInstance();
23.
24.
if
( log.loggedPojos ==
null
)
25.
log.loggedPojos = map;
26.
else
27.
log.loggedPojos.putAll( map );
28.
}
29.
}
The most important part of the magic is accomplished by getting each POJO to implement the following interface:
1.
package
com.etretatlogiciels.pojo;
2.
3.
import
java.util.Map;
4.
5.
public
interface
PojoInterface
6.
{
7.
public
Map< String, String > toHashMap();
8.
}
Here's one of the POJOs:
1.
package
com.etretatlogiciels.pojo;
2.
3.
import
java.io.Serializable;
4.
5.
public
class
Person
implements
Serializable, PojoInterface
6.
{
7.
private
String name;
8.
...
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:
01.
import
java.util.List;
02.
03.
...
04.
05.
06.
public
static
< T
extends
PojoInterface >
void
logPojoList(
int
which, List< T > pojoList )
07.
{
08.
int
i =
1
;
09.
10.
for
( PojoInterface pojo : pojoList )
11.
{
12.
String string = pojo.toString();
13.
Map< String, String > map =
new
HashMap< String, String >(
1
);
14.
map.put( i+
""
, string );
15.
accumulatePojos( map );
16.
17.
i++;
18.
}
19.
}
20.
21.
...
* POJO: "plain, old Java object," i.e.: a class expressing a very simple data object, sometimes also called a bean.