gpt4 book ai didi

java - 为什么我可以在 InvocableHandler 的 invoke() 方法中调用 proxy.getClass() ?

转载 作者:行者123 更新时间:2023-12-01 10:11:34 25 4
gpt4 key购买 nike

这是“Thinking in Java”中经过修改的动态代理示例。

import java.lang.reflect.*;

interface Interface { void foo(); }

class RealObject implements Interface {
public void foo() {}
}

class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object
invoke(Object proxy, Method method, Object[] args)
throws Throwable {
proxy.toString();
return method.invoke(proxied, args);
}
}

public class ProxyTest {
public static void main(String args[]) {
RealObject real = new RealObject();
Interface proxy = (Interface)Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[]{ Interface.class },
new DynamicProxyHandler(real));
proxy.foo();
}
}

在上面的例子中,我调用 toString()里面的方法invoke()方法。正如我所料,会发生无限递归,因为调用代理的 toString()方法将再次调用 Handler。

Bruce Eckel 在《Thinking in Java》中是这样说的:

However, be careful when calling methods on the proxy inside invoke(), because calls through the interface are redirected through the proxy.

异常详细信息:

Exception in thread "main" java.lang.StackOverflowError
at DynamicProxyHandler.invoke(ProxyTest.java:19)
at $Proxy0.toString(Unknown Source)
at DynamicProxyHandler.invoke(ProxyTest.java:19)
at $Proxy0.toString(Unknown Source)
...

但是,如果我替换 proxy.getClass();对于 proxy.toString(); :

public Object 
invoke(Object proxy, Method method, Object[] args)
throws Throwable {
proxy.getClass();
return method.invoke(proxied, args);
}

一切都好。没有堆栈溢出错误。没有无限递归。

我还尝试替换 proxy.toString();proxy.hashCode();proxy.equals("foo"); 。它们也导致了 StackOverflowError。

为什么是getClass()不同于toString() , hashCode() ,和equals()

最佳答案

答案可以在Proxy类的文档中找到:https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html

An invocation of the hashCode, equals, or toString methods declared in java.lang.Object on a proxy instance will be encoded and dispatched to the invocation handler's invoke method in the same manner as interface method invocations are encoded and dispatched, as described above. The declaring class of the Method object passed to invoke will be java.lang.Object. Other public methods of a proxy instance inherited from java.lang.Object are not overridden by a proxy class, so invocations of those methods behave like they do for instances of java.lang.Object.

另外,我认为这与 toString() 方法有一个默认定义有关:

public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

getClass()(以及wait()notify()等)定义为:

public final native Class<?> getClass();

因此,要区分哪些方法不会被代理,您可以查看方法定义中是否存在 final native

关于java - 为什么我可以在 InvocableHandler 的 invoke() 方法中调用 proxy.getClass() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36097447/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com