2016-08-24 5 views
5

私はこのテストクラスを書いていますが、なぜプロキシオブジェクトが元のオブジェクトと同じhashCodeを持っているのでしょうか?なぜ誰が知っていますか?サンプル出力厥Java Proxy - >なぜ元のオブジェクトのようなプロキシオブジェクトと同じ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

'Service'、' Subject_A'、 'ProxyGenerator'とは何ですか?これらはある図書館のものか、それともあなたが書いたものですか? – Codebender

+1

[JavaでequalsとhashCodeをオーバーライドするときに考慮すべき問題は何ですか?](http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals- hashcode-in-java) – Raedwald

答えて

3

プロキシは間接的限りクライアントコードは、プロキシの存在が隠されるべきに関しては、基礎となるオブジェクトにアクセスするために使用されます。

通常、このパターンは、トランザクションやセキュリティ機能でオブジェクトを装飾するためのスプリングや休止状態などのフレームワークで使用されます。 上記を踏まえて、代理オブジェクトは、hashcode(),equals()およびtoString()の出力を基本オブジェクトとして持つことは当然のことです。

編集

アップデートは、すべての@Holger

まずからの修正に応じて、何を観察することはtoString()コール、ないhashcode()で同じ出力です。 プロキシを使用したequals()の実装は、一見すると少し微妙です。 equals()の典型的な実装では、対称性の特性は等しい契約に応じて違反されるであろう:null以外の参照値xとyの

及び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 

持っている:@Holgerは、同じ基本インスタンスをラップする2つのプロキシを通り

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

を、等しくすることができ対称性を損なうことなく

プロキシをラップされたインスタンスと等しくするオプションは、オブジェクトの等価性を構成し、このインターフェイスに対してクラスを比較する状態に対して、インターフェイスメンバー(ゲッター)によってequalsを実装することができます。プロキシと基本オブジェクトの両方がこのインタフェースに準拠しているので、それらは等しいでしょう。

+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'呼び出しを別のオブジェクトに直接委譲させることは良い考えではありません。しかし、あなたは可能です。同じオブジェクトをラップする2つのプロキシが等しい方法で実装します。それは契約に準拠します。 – Holger

関連する問題