2016-08-24 53 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