I was dealing with hibernate, trying to figure out the run-time class behind proxied instances by using the visitor pattern. I then came up with an AbstractVisitable
approach, but I wonder if it will always produce correct results.
Consider the following code:
interface Visitable {
public void accept(Visitor v);
}
interface Visitor {
public void visit(Visitable visitorHost);
}
abstract class AbstractVisitable implements Visitable {
@Override
public void accept(Visitor v) {
v.visit(this);
}
}
class ConcreteVisitable extends AbstractVisitable {
public static void main(String[] args) {
final Visitable visitable = new ConcreteVisitable();
final Visitable proxyVisitable = (Visitable) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] { Visitable.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
return method.invoke(visitable, args);
}
});
proxyVisitable.accept(new Visitor() {
@Override
public void visit(Visitable visitorHost) {
System.out.println(visitorHost.getClass());
}
});
}
}
This makes a ConcreteVisitable
which inherits the accept
method from AbstractVisitable
. In c++, I would consider this risky, since this
in AbstractVisitable could be referencing to AbstractVisitable::this
, and not ConcreteVisitable::this
. I was worried that the code under certain circumstances would print class AbstractVisible
. Yet the code above outputs class ConcreteVisitable
, even though I hid the real type behind a dynamic proxy (the most difficult case I could come up with). Is the abstract visitor approach above guaranteed to work, or are there some pitfalls with this approach?
What guarantees are given in Java with respect to the this
pointer?