Why am I getting a ClassCastException when the class is clearly of the right type?

Apache NetBeans Wiki Index

Note: These pages are being reviewed.

Q: I am getting an exception when I run my module, such as

java.lang.ClassCastException: Implementation cannot be cast to Interface
        at Factory.newInstance (Factory.java:123)

But Implementation implements Interface, so why is this a CCE?

A: Usually this is because the Interface that Implementation actually implements was loaded from a different class loader than what Factory sees.

That is very likely the immediate cause of the CCE. The root cause is not always obvious, but it is likely to be that some code uses Thread.currentThread().getContextClassLoader() to load a class by name. In NB by default the context class loader just looks around in loaded modules (lacking any better information), so it is possible for the following situation to arise:

module A: Interface, Factory
module B > A: Implementation implements Interface
module C: Interface, Factory
module D > A: Implementation implements Interface

where Factory does something like:

Interface i = (Interface) Class.forName("Implementation", true,
    Thread.currentThread().getContextClassLoader()).newInstance();

(This is a common design pattern for XML parsers, etc.)

Now if A’s Factory happens to get D’s Implementation (or C’s gets B’s) then you get a CCE at runtime.

An especially silly variant of this problem, known to occur at least in Xerces (), is that Implementation actually resides in the same JAR as Interface and Factory, and is the standard impl almost everyone uses unless overridden somehow - yet Factory loads it by name from the CCL rather than simply loading it directly using e.g. new Implementation().

The usual workaround is to wrap the problematic call(s) in a dynamic block:

ClassLoader orig = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(SomeReferenceClass.class.getClassLoader());
try {
  Factory.load(...);
} finally {
  Thread.currentThread().setContextClassLoader(orig);
}

Note: NetBeans forbids ambiguous delegations. () If a class could be loaded from two (or more) places, it will not be loaded at all. This does not solve your problem but it at least ensures it gets reported more reliably and with a descriptive message rather than an odd ClassCastException.

Applies to: NetBeans 6.5 and later