0

我正在处理休眠,试图通过使用访问者模式找出代理实例背后的运行时类。然后我想出了一个AbstractVisitable方法,但我想知道它是否总是会产生正确的结果。

考虑以下代码:

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());
            }
        });
    }
}

这使得 a ConcreteVisitablewhich 从 继承accept方法AbstractVisitable。在 c++ 中,我认为这是有风险的,因为this在 AbstractVisitable 中可能引用AbstractVisitable::this,而不是ConcreteVisitable::this。我担心某些情况下的代码会打印class AbstractVisible. 然而,上面的代码输出class ConcreteVisitable,即使我将真实类型隐藏在动态代理后面(我能想到的最困难的情况)。上面的抽象访问者方法是否可以保证工作,或者这种方法是否存在一些缺陷?

thisJava 中关于指针的保证是什么?

4

2 回答 2

2

this正如您可能猜到的那样,它总是指向这个对象。您使用它的层次结构中的哪种类型无关紧要,除非您使用它来引用非虚拟事物(例如私有字段/方法,或者上帝禁止的静态方法)。 getClass()是虚拟的。

现在我希望您可能会混淆this认为 Java 具有多次调度的行为。它没有。如果您将访客更改为:

class Visitor {
    public void visit(Visitable visitorHost);
    public void visit(ConcreteVisitable visitorHost);
}

然后像这样实现它:

public void visit(Visitable visitorHost) { 
   System.out.println("Visitable"); 
}
public void visit(ConcreteVisitable visitorHost) {
   System.out.println("ConcreteVisitable"); 
}

它确实会打印“Visitable”,而不是“ConcreteVisitable”,因为 Java 不执行double dispatch

于 2010-06-14T14:10:27.963 回答
0

您的动态代理将 accept(...) 调用传递给底层的 Visitable,然后调用 visit(...),将自身作为参数传递。除了通过 accept() 调用之外,代理从不参与任何事情,所以当它到达 visit(...) 方法的实现时,正在处理的 Visitable 是具体的实例,被代理剪掉了。

于 2010-06-14T15:04:35.403 回答