DataObjects wrap FileObjects. A FileObject is just a container for data; it happens to have a MIME type, but like, it doesn't know or care what kind of file it represents, or what the file is. DataObject is part of the Loaders API - a good overview of this API can be found here.

A DataObject represents one or more (typically only one) FileObjects. A DataObjectknows what kind of a file it represents; it may represent the parsed contents of a file such as a .java file; or, as in the case of InstanceDataObject the file name may provide all the information it needs to be useful.

DataObjects are produced by DataLoaders, which modules register for specific file types. So for each file type, there is (usually) one DataLoader; and for each file of that type, there is (typically) one DataObject.

DataObjects are seldom referred to by type - if you are casting a DataObject to its implementation class, you are probably doing something wrong. The usage pattern is to ask a DataObject for instances of interfaces that are the things your code will actually interact with. The method for doing this is DataObject.getCookie(Class class).

As a simple example, the NetBeans APIs define an interface org.openide.cookies.OpenCookie. It has one method, open(). That method will open the file in the editor. What exactly will happen when open() is called is entirely up to the module that implements the DataObject. The rest of the system does not need to know any of the implementation details - it just needs to know if the DataObject has an OpenCookie. If it does, then the Open action on its context menu can be enabled, and that action will call ((OpenCookie) theDataObject.getCookie(OpenCookie.class)).open().

The name cookie is historical and somewhat unfortunate; the getCookie() pattern is an older variation on the Lookup pattern for service discovery. The two are equivalent, with the exception that getCookie() requires all returned objects to implement the empty Node.Cookie marker interface, and Lookup can return any object. Expect getCookie() to be replaced with a new getLookup() method at some point in the future.

As suggested above, a DataObject may actually represent more than one file - so when you expand a folder in the UI, there may actually be fewer DataObjects in that folder than there are files. This is why, in the NetBeans IDE, a Swing form is represented by a .java file and a corresponding .form file, but the .form file is not visible in the UI; in the past, .properties files have also used this mechanism to present resource bundles in various languages as a single node in the files tree.

However, this ability to represent multiple files with a single DataObject is strongly discouraged for new code and will probably eventually be deprecated - it has serious negative implications for scalability.

Source: NetBeans FAQ