Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Proxy -> Why does have proxy object same hashCode like original object

Tags:

java

I have written this test class and I am wondering why proxy object does have the same hashCode like original object. Does anyone know why?

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);
}
}

Thats an sample output:

in Subject_A#work: str = Hello
hello = Hello_DONE


realSubject: at.me.proxy.Subject_A@4f4a7090
proxySubject: at.me.proxy.Subject_A@4f4a7090
like image 736
quma Avatar asked Oct 18 '22 03:10

quma


1 Answers

Proxies are used to indirectly access underlying object and as far as client code is concerned the existence of proxy should be hidden.

Typically this pattern is used in frameworks such as spring and hibernate to decorate your objects with transaction or security capabilities. Given the above, it is only natural that the proxy object has same output for hashcode(), equals() and toString() as the underlying object.

Edit

Update according to corrections from @Holger

First of all, what you observed is same output for toString() call, not hashcode(). The implementation of equals() via proxies is a bit more subtle than at first glance. In typical implementation of equals(), the property of symmetry would be violated according to equals contract:

for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

and there you have

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

but

wrapped.equals(proxy); // false

due to:

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

As @Holger suggests, two proxies wrapping same underlying instance, could be equal without violation of symmetry.

An option to make proxy equal to wrapped instance and vice versa could be to implement equals via interface members(getters) for state that comprises object equality and compare classes against this interface. Since both proxy and underlying object conform to this interface they would be equal.

like image 79
John Avatar answered Nov 02 '22 07:11

John