Java 抽象访问者 - 保证成功吗?如果是这样,为什么?

发布于 2024-09-06 06:02:14 字数 1720 浏览 8 评论 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());
            }
        });
    }
}

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

Java 中对于 this 指针给出了哪些保证?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

与之呼应 2024-09-13 06:02:14

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

现在我预计您可能会混淆 this 的行为,认为 Java 具有多重分派。事实并非如此。如果你将你的 Visitor 更改为这样:

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 不执行 双重调度

this always points to this object, as you might guess. Which type in the hierarchy you use it from is irrelevant, unless you're using it to reference non-virtual things (like private fields/methods, or God forbid, static methods). getClass() is virtual.

Now I expect maybe you're confusing the behaviour of this for thinking Java has multiple dispatch. It doesn't. If you change your Visitor to this:

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

And then implemented it like this:

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

It would indeed print "Visitable", not "ConcreteVisitable" since Java does not perform double dispatch.

不羁少年 2024-09-13 06:02:14

您的动态代理将accept(...) 调用传递给底层的Visible,然后调用visit(...),并将其自身作为参数传递。除了传递accept()调用之外,代理从不参与任何事情,因此当它实现visit(...)方法时,所处理的Visible是代理的具体实例。

Your dynamic proxy passes the accept(...) call through to the underlying Visitable, which then calls visit(...), passing itself as the argument. The proxy is never involved in anything except passing through the accept() call, so by the time it gets to the implementation of the visit(...) method, the Visitable being dealt with is the concrete instance, shorn of the proxy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文