10

Although the Java docs specify, that Weak references are primarily for canonicalizing mappings, you will find many, many, many people on the internet stating, that the WeakHashMap is perfect for storing object metadata during its lifetime. However, nobody bothers to make a comprehensible AND appropriate example.

Using WeakHashMap to add object some properties or store metadata sounds to me, like an arbitrary decision based on the will to just use the damn thing. In other words - a bad design. I understand, that there are situations where inheritance may not be available (final classes, interfaces), but what about composition? I can't think of one example where composition would not be an option. And certainly a better one, because it relies on a well-established principle, instead of a "language quirk".

So, is there a situation, where it would be better to use weak references instead of simple composition? If not, why does everyone on the internet seem to get it wrong?

Leprechaun
  • 240
  • 1
  • 6
  • Logic error: "...arbitrary decision based on the will to just use the damn thing. In other words - a bad design." The ends might not justify the means, but the means are not sufficient to controvert the ends. Given the same methods the result could hypothetically be a good design. Though for this case I would not argue it. :) – cwharris Feb 07 '17 at 22:45
  • 3
    Weak references are an orthogonal concept to composition and inheritance. – Robert Harvey Feb 08 '17 at 00:03

1 Answers1

13

Let's say I need to associate some metadata with some data objects. This is a pretty common scenario. I don't control the data objects, and there's lots of them, and the API in question (callbacks, virtual methods, etc..) offers me those data objects, but without my metadata. So, I need to track some state for each of those data objects, namely the ones I've seen before and might see again. I'll call this metadata an adornment, which is a term sometimes used for that concept.

Simple composition provides for easy lookup from the adorning object (the one with metadata) to the other object (the one with data), with the presumption that since I control the metadata object design, I can put therein a reference directly to the data object.

However, unless you control the design of the data object and can change it, simple composition doesn't provide the reverse lookup (from data object to some metadata). In fact, unless you have a collection of the metadata objects, you can't even locate the associated metadata item given an object (data) item.

In addition to the problem of lookup in the direction going from the object to find its adorning metadata, there is also the problem of metadata lifetime.

Metadata that accumulates and is never released even when the data object is no longer used is a memory leak.

A weak referencing hashmap solves both problems. It allows locating the metadata given the data, and allows the metadata to be freed at some time after the data is freed.

Note further that a weak referencing hashmap allows not only (metadata) values to be reclaimed (gc'ed), but also the (data) keys to be reclaimed (gc'ed), since if the keys were kept that would also be a memory leak, and further, the values could never be released either.

Erik Eidt
  • 33,282
  • 5
  • 57
  • 91
  • Why doesn't using the data objects with a weak-hashmap-backed metadata table count as composition? – Jack Feb 07 '17 at 23:44
  • 2
    @Jack, Composition, especially "simple composition" in my mind at least, is objects referring to other objects, but directly so. The "has-a" relationship of composition is expressed using a simple reference, or sometimes a collection. Here the hashmap is an indirect method. You can't reach the adornment if you don't have the hashmap. Whereas in composition you can do this navigation. Thus, I prefer to call this metadata an adornment rather than composition, but they are certainly related. FWIW, the adornment does (IMHO) compose with the data, just not the other way around. – Erik Eidt Feb 07 '17 at 23:55
  • @Jack, re: my last FWIW, I just realized that when using the weak hashmap you wouldn't normally put a reference from the metadata adorning object to the other because of memory holding (or if you did want the has-a in that direction, it would have to be a weak reference). So, typically the weak hashmap client works with two obects that are effectively paired to each other but are not technically in object composition with each other. – Erik Eidt Feb 08 '17 at 16:44