All of these are really historical variations on the same theme. In all cases, you pass a Class object and get back null or an instance of that class. You can see the progression in genericness:

SharedClassObject is the oldest version of the Lookup pattern in NetBeans APIs, dating to circa 1997 (because of various performance issues, eventually all usages of SharedClassObject should be deprecated and removed from the APIs). You'll see that form used in SystemOption for storing settings, and most of the singleton Action objects in the actions API. All objects returned by it will be instances of SharedClassObject.

getCookie() (circa 1999) is specific to Nodes and DataObjects. It uses the same pattern, but all objects returned by it will implement the empty Node.Cookie marker interface.

The down-side to both of the above is that they specify the return type. In the case of Node.Cookie, in practice, this meant that anything that might possibly need to be provided by a DataObject or Node needed to implement this silly marker interface, forcing it to have a dependency on the Nodes API, or a wrapper Cookie class had to be created to provide the underlying object, which just added useless classes and noise.

Lookup is the most modern and generic version of this pattern, and probably the final one (it will probably evolve somewhat, but compatibly, once it is possible to use generics in NetBeans APIs). It offers two advantages:

  1. Its return type is java.lang.Object, so it can be used directly with anything
  2. Having objects own a lookup rather than directly providing a lookup(Class c) method makes it easier to replace or proxy the Lookup of some object

Source: NetBeans FAQ