Why use this strange convention - wouldn't a Map be good enough?
Other platforms do use string-keyed maps for this sort of thing, but there are some weaknesses with that approach:
- it is impossible to enforce dependencies. With Lookup, a module's code cannot request an object of type X unless it can load/access the
X.class. The module trying to look up an X will not be able to see
X.classunless it declares a dependency on the module that defines X and the module which defines X says that it allows access to the Java package X lives in. (A Map<Class<T>,T> would do the same job as Lookup.)
- The class of values in a map can change without notice - so if you have (SomeIface) foo = (SomeIface) globalMap.get("foo"), some new version of the module that provides "foo" can change the return type, causing ClassCastException s; with Lookup, you cannot ever get an object that is not of the type you passed in the request - so Lookup's approach is more robust.
- Lookup supports listening to changes in the result.
- Lookup supports multiple instances for one key - if you call
lookup(X.class)you get one instance. If you call
lookupAll(X.class)you get a
Collection<? extends X>(so with
lookupAll()it is more like a Map<Class<T>,List<T>>)
There are some other capabilities of Lookup (such as getting the specific type or number of results without actually creating objects, and providing named result items) but these are rarely used in practice.
Lookup is very powerful, yet simple and generic; people quickly learn to love it, once they realize what it can do.
See also the javadoc: org.openide.util.Lookup