使用JDK Dynamic Proxies实现equals()

Ala*_*n47 5 java proxy equals dynamic-proxy

我有史以来第一次使用标准JDK动态代理实现自己的代理类.它的工作原理相当不错,除了一个细节:equals(...)方法.

我们假设我们有一个像这样的简单接口,我们要代理它:

public interface MyInterface {
    public String getID();
    public void setID(String id);
}
Run Code Online (Sandbox Code Playgroud)

......我们的实现看起来是这样的(标准的Java Bean与生成hashCode()equals):

public class MyImplementation implements MyInterface {
    private String id;

    public String getID() { return this.id; }
    public void setID(String id) { this.id = id; }

    // hash code & equals generated by eclipse

    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (this.databaseId == null ? 0 :      
        this.id.hashCode());
        return result;
    }

    public final boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (this.getClass() != obj.getClass()) {
            return false;
        }
        MyImplementation other = (MyImplementation) obj;
        if (this.databaseId == null) {
            if (other.databaseId != null) {
                return false;
            }
        } else if (!this.databaseId.equals(other.databaseId)) {
            return false;
        }
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,当我创建代理时,该equals(...)方法不再是对称的:

original.equals(original); // true
proxy.equals(original);    // true, as the proxy forwards the call to the wrapped object
original.equals(proxy);    // false
proxy.equals(proxy);       // false
Run Code Online (Sandbox Code Playgroud)

本文还讨论了这一点.

我的问题是:如果我想要提供所有四个"平等"案例true,那么最好的(即最安全和最少侵入性)方式是什么?

小智 2

这是 equals() 的可能替代方案;

public final boolean equals(final Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (! (obj instanceof MyInterface)) // neither a Proxy nor a MyImplementation
    return false;

    MyInterface other = (MyInterface) obj;
    if (this.getID() == null) {
       if (other.getID() != null) {
               return false;
       }
    } else if (!this.getID().equals(other.getID())) {
      return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

此代码使用 getID() 而不是直接访问该字段。到目前为止,效果很好。