2016-08-24 1 views
5

Я написал этот тестовый класс, и мне интересно, почему у прокси-объекта есть тот же хэш-код, что и исходный объект. Кто-нибудь знает, почему?Java Proxy -> Почему у прокси-объекта такой же хэш-код, как и у исходного объекта

public class Main { 

public static void main(String[] args) { 
    final Service realSubject = new Subject_A(); 
    final Service proxySubject = ProxyGenerator.makeProxy(Service.class, realSubject); 
    final String hello = proxySubject.work("Hello"); 
    System.out.println("hello = " + hello); 
    System.out.println("\n"); 
    System.out.println("realSubject: " + realSubject); 
    System.out.println("proxySubject: " + proxySubject); 
} 
} 

То выход образца:

in Subject_A#work: str = Hello 
hello = Hello_DONE 


realSubject: [email protected] 
proxySubject: [email protected] 
+2

Вы не называете '.hashCode()' в своем коде, поэтому я не вижу, какой ответ вы ожидаете. Образец вывода, пожалуйста? – fge

+0

Что такое 'Сервис',' Subject_A' и 'ProxyGenerator'? Являются ли они из какой-то библиотеки или вы их написали? – Codebender

+1

Возможный дубликат [Какие проблемы следует учитывать при переопределении равных и hashCode в Java?] (Http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and- hashcode-in-java) – Raedwald

ответ

3

Доверенные используются для непрямого доступа к базовым объектам и, насколько код клиента обеспокоен наличие прокси-сервера должны быть скрыты.

Обычно этот шаблон используется в таких рамках, как весна и спящий режим, чтобы украсить ваши объекты транзакциями или возможностями безопасности. Учитывая вышеизложенное, вполне естественно, что прокси-объект имеет одинаковый выход для hashcode(), equals() и toString() в качестве основного объекта.

Редактировать

Обновление в соответствии с поправками от @Holger

Прежде всего, то, что вы наблюдали такое же выход для toString() вызова, а не hashcode(). Реализация equals() через прокси-серверы немного более тонкая, чем на первый взгляд. В типичной реализации equals(), свойство симметрии будет нарушено в соответствии с договором РАВНО:

для любых ненулевых значений ссылок х и у, x.equals (у) должна возвращать истинна тогда и только тогда, когда у. equals (x) возвращает true.

и у вас есть

// works since you delegate same instance of wrapped class to underyling object 
proxy.equals(wrapped); // true 

но

wrapped.equals(proxy); // false 

из-за:

// proxy class != wrapped class 
if (this.getClass() != obj.getClass()) { 
     return false; 
} 

Как следует @Holger, два прокси оберточной одинаковый базовый экземпляр, может быть равна без нарушения симметрии.

Возможность сделать прокси равным обернутому экземпляру и наоборот может быть реализована равными через интерфейсные элементы (getters) для состояния, которое содержит равенство объектов и сравнивает классы с этим интерфейсом. Поскольку оба прокси и базовый объект соответствуют этому интерфейсу, они будут равны.

+1

Я должен возразить против идеи делегирования «равно», поскольку результат нарушит договор симметрии; прокси утверждал бы, что он равен исходному объекту, тогда как исходный объект обычно не будет равен прокси.Но вы указываете в правильном направлении: то, что мы видим здесь, - это делеция 'toString()' в действии, производя тот же вывод для исходного объекта и прокси, но в этом коде нет доказательств того, что 'hashCode' будет делегированы также. – Holger

+0

@ Хольджер, возможно, неверно истолковал: * Вызов методов hashCode, equals или toString, объявленных в java.lang.Object на экземпляре прокси, будет закодирован и отправлен методу вызова обработчика вызова таким же образом, как и вызовы метода интерфейса закодированы и отправлены, как описано выше * из [docs]: https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html. Однако мне кажется, что 'equals()', 'hashcode()' и 'toString()' обрабатываются одинаково. – John

+0

Правильно, что все они делегированы 'InvocationHandler', но это решение этого обработчика, как обрабатывать их. И позволить обработчику напрямую делегировать вызов «равно» другому объекту, это не очень хорошая идея. Но вы можете, например. реализуйте его так, чтобы два прокси, обертывающих один и тот же объект, были равны. Это будет соответствовать контракту. – Holger

Смежные вопросы