Given an class hierarchy:
A -> B -> C -> instanceOfC
is it possible (and how) to insert a class, temporarily, at runtime, like so:
A -> B -> B' -> C -> instanceOfC?
It's possible if you use AspectJ. AspectJ has a declare parents statement that enables you to do exactly that, and through Load Time Weaving you should be able to do it at runtime, also. However, you will not be able to do it on already loaded classes (at least not easily, maybe it works if you unload the class first).
Reference:
But methinks you are trying to solve the wrong problem here. I'd say try to replace inheritance with aggregation, let C have a member of type D to which functionality is delegated and just pass in a different implementation of D. That's called the strategy pattern, and it's a much cleaner way to do things (and it's testable too)
The API that allows the most invasive changes into a running JVM is probably the JVM Tool Interface. It is designed to develop debuggers that can dynamically change methods during runtime to facilitate fix-and-continue debugging.
The relevant call for replacing the definition of a class would be RedefineClass. However, the documentation says that it can't be used to change the hierarchy of a class:
The redefinition must not add, remove or rename fields or methods, change the signatures of methods, change modifiers, or change inheritance.
Therefore I'd say that you can't sanely modify the type hierarchy of already-loaded classes in an unmodified JVM. Either change the class hierarchy during loading (with a custom ClassLoader and bytecode-instrumentation, possibly using AOP) or find another approach.
No, you can not.
You can do:
A -> | interface for B and B` | -> C
or
| B | -> C
A ->
| B` | -> C`
Losing some good manners, you could do B + inner class = B'.
For example:
public class B<extraFunctionalityClassOrInterface> extends A {
private extraFunctionalityClassOrInterface eF = null;
// and B contents
}
If instance of b.eF == null then you can conclude b != B', but b == B.
I'm not 100%, but I think this would only be possible if both B' and C were dynamically loaded.