これは、「Thinking in Java」の変更された動的プロキシの例です。上記の例でInvokeHandlerのinvoke()メソッド内でproxy.getClass()を呼び出すのはなぜですか?
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();
}
}
、Iはinvoke()
方法内側toString()
メソッドを呼び出します。私が予想したように、プロキシのtoString()
メソッドを呼び出すと再びハンドラが呼び出されるため、無限の再帰が発生します。
これはブルースEckel氏は、「Javaで考える」で述べてどのようである: invoke()
、内部プロキシのメソッドを呼び出すときにインターフェイスを介して通話が プロキシ経由でリダイレクトされるので
しかし、注意してください。
例外の詳細:
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.toString();
ためproxy.getClass();
に置き換えた場合:
public Object
invoke(Object proxy, Method method, Object[] args)
throws Throwable {
proxy.getClass();
return method.invoke(proxied, args);
}
すべてがOKです。 No StackOverflowError。無限再帰はありません。
また、proxy.toString();
をproxy.hashCode();
またはproxy.equals("foo");
に置き換えようとしました。 StackOverflowErrorも発生しました。
なぜgetClass()
がtoString()
,hashCode()
、equals()
と異なるのですか?
'getClass()'は、 'Obect'クラスによって実装された最終的なメソッドです。上書きすることはできません。 – saka1029