How General Should Generic Wildcard Captures Be?

by

In working on the next release of LingPipe, I’m finding many opportunities to generalize the generic types. Let’s take the cached feature parser I’m working on right now in the other window. Feature vectors are extracted as instances of

Map<String, ? extends Number>

I had to do that to allow LingPipe utility classes like

util.ObjectToCounterMap<String> extends Map<String, Counter>

and

util.ObjectToDoubleMap<String> extends Map<String, Double>

to be usable as collectors for feature extractors.

The cached feature parser accepts a map that’ll act as a cache for feature vectors. The most general type that’d work is:

Map<? super E, ? extends Map<String, ? extends Number>>

Intuitively (?!), this says that we need any old map (it can be a subtype for the outer type) that can hold mappings from E objects to results that implement maps from strings to numbers.

But is anyone other than an obsessive type geek going to be able to even parse the expression? Should I just go with the simpler form here:

Map<E, Map<String, ? extends Number>>

I think it makes sense to use the simpler form in this setting because it’s going to be a cache that gets constructed under the user’s control and most of the constructors for these kinds of maps are very general (e.g. all of Java’s Map implementations and LingPipe’s util.FastCache implementation).

You might think making the nested types covariant would help, but as Josh Bloch points out in Effective Java (2nd Ed.), this is problematic because the direction of subclassing differs for arguments and return results. That’s why there are both super and extends in the wildcard capture definitions above. In the simplest case, you extend return results and super arguments.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s