2016-03-19 15 views
0

Bu, "Java'da Düşünme" den değiştirilmiş dinamik proxy örneğidir.Neden proxy.getClass() öğesini InvocationHandler's invoke() yönteminin içinde arayabilirim?

Yukarıdaki örnekte
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() yöntem içinde toString() yöntemi arayın. Beklediğim gibi, sonsuz yineleme gerçekleşecek çünkü proxy'nin toString() yöntemini çağırması İşleyiciyi tekrar çağırır.

Bu

Bruce Eckel "Java Düşünme" dedi nasıl: arayüz üzerinden çağrılar vekil aracılığıyla yönlendirilir, çünkü invoke() iç vekil üzerindeki yöntemleri çağrılırken

Ancak dikkatli olun.

İstisna ayrıntıları:

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) 
    ... 

Ama proxy.toString(); için proxy.getClass(); yerine eğer:

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

Herşey yolunda. StackOverflowError yok. Sonsuz özyineleme yok.

Ayrıca proxy.toString();'u proxy.hashCode(); veya proxy.equals("foo"); ile değiştirmeyi denedim. StackOverflowError'a da neden oldular.

Neden getClass()toString(), hashCode() ve equals() farklı?

+0

'getClass()' 'Obect' sınıfı tarafından uygulanan son bir yöntemdir. Bu aşırıya kaçmaz değil. – saka1029

cevap

1

Cevap Proxy sınıfı belgelerinde bulunabilir: https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html

hashCode bir çağırma, eşit veya toString yöntemleri bir proxy örneğinde java.lang.Object bildirilen kodlanmış ve sevk edilecek Çağırma işleyicisinin yöntemini, aynı şekilde, arabirim yöntemi çağırmalarının, yukarıda açıklandığı gibi kodlanması ve gönderilmesi ile aynı şekilde gerçekleştirmesi. Method nesnesinin bildirme aşamasına geçtiği bildirilen sınıf java.lang.Object olacaktır. Java.lang.Object öğesinden devralınan bir proxy örneğinin diğer genel yöntemleri, bir proxy sınıfı tarafından geçersiz kılmamaktadır, bu nedenle bu yöntemlerin çağrılması, java.lang.Object örneklerinde olduğu gibi davranır. Ayrıca

, ben toString() yöntemi varsayılan bir tanıma sahip olduğu gerçeği ile ilgili bir şey olduğunu düşünüyorum:

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

getClass() (ve wait(), notify() vs.) tanımlanırken olarak:

public final native Class<?> getClass(); 

Bu nedenle, hangi yöntemlerin proxy edilmeyeceğini ayırt etmek için yöntem tanımında final native varlığını bulabilirsiniz. n.

İlgili konular