2016-08-24 84 views
5

我已經寫了這個測試類,我想知道爲什麼代理對象有像原始對象一樣的hashCode。有誰知道爲什麼?Java代理 - >爲什麼代理對象像原始對象一樣hashCode

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

什麼是「服務」,「主題A」和「代理生成器」?這些來自某個圖書館還是你寫的? – Codebender

+1

可能重複[在Java中重寫equals和hashCode時應考慮哪些問題?](http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and- hashcode-in-java) – Raedwald

回答

3

代理被用來間接訪問底層對象並儘可能客戶代碼而言代理的存在應該被隱藏。

通常,這種模式用於像spring和hibernate這樣的框架中,用事務或安全功能來裝飾對象。 鑑於上述情況,代理對象具有與hashcode()equals()toString()相同的輸出作爲基礎對象是很自然的。

編輯

根據從@Holger

首先更正更新,你觀察到的東西是相同的輸出toString()調用,不hashcode()。 通過代理執行equals()比乍一看更加微妙。在典型的實施equals(),對稱的性質將按照平等合同侵犯:

對於任何非空引用值x和y,x.equals(Y)應返回true當且僅當年。 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表明,兩個代理包裝相同的底層的實例,可以等於沒有違反對稱性。

可以通過接口成員(獲得者)將代理等同於包裝實例並反之亦然的選項用於包含對象相等的狀態並根據此接口比較類。由於代理和基礎對象符合這個接口,它們將是平等的。

+1

我不得不反對委託'equals'的結果會違反對稱合約;該代理將聲稱與原始對象相同,而原始對象通常不會與代理相同。但是你指出了正確的方向:我們在這裏看到的是'toString()'的代表,它爲原始對象和代理生成了相同的輸出,但是在這段代碼中沒有證據表明'hashCode'將會是也委託。 – Holger

+0

@Holger我可能誤解了:*在代理實例中對java.lang.Object中聲明的hashCode,equals或toString方法的調用將被編碼並調用到調用處理程序的invoke方法中,方式與接口方法調用相同如上所述*從[docs]中進行編碼和分派:https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html。然而,在我看來,equals(),hashcode()和toString()是以相同的方式處理的。 – John

+0

這是正確的,它們都被委託給了'InvocationHandler',但它是處理程序的決定,如何處理它們。讓處理程序直接將「equals」調用委託給另一個對象,這不是一個好主意。但是,你可以,例如以包含相同對象的兩個代理相等的方式實現它。這將符合合同。 – Holger