Java 使用JDK动态代理实现equals()
有史以来第一次,我必须使用标准JDK动态代理实现自己的代理类。它工作得相当好,除了一个细节:Java 使用JDK动态代理实现equals(),java,proxy,equals,dynamic-proxy,Java,Proxy,Equals,Dynamic Proxy,有史以来第一次,我必须使用标准JDK动态代理实现自己的代理类。它工作得相当好,除了一个细节:equals(…)方法 假设我们有这样一个简单的接口,我们想代理它: public interface MyInterface { public String getID(); public void setID(String id); } 。。。我们的实现如下所示(带有生成的hashCode()和等于的标准Java Bean): 问题是,当我创建代理时,equals(…)方法不再是对称
equals(…)
方法
假设我们有这样一个简单的接口,我们想代理它:
public interface MyInterface {
public String getID();
public void setID(String id);
}
。。。我们的实现如下所示(带有生成的hashCode()
和等于的标准Java Bean):
问题是,当我创建代理时,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
这也将在中讨论
我的问题是:如果我想让所有四个“equals”案例都提供true
,那么最好的方法是什么(即最安全和最少干扰)?这里有一个equals()的可能替代方案
此代码使用getID()而不是直接访问字段。到目前为止,它运行良好。您将找到一个可行的解决方案。但有一个巨大的问题:
要相互比较的两个对象都必须知道代理包装
JAVA在技术环境中做到了这一点,即代理的处理与其他对象相同。但是
我在这个问题上的个人观点是:JAVA应该引入对代理的内置支持,一旦调用hashcode和equals,代理就可以在内部展开
代理应该对“正常”实现透明。你不应该为你是否有代理或原件而烦恼。但是JAVA这样做是错误的
一种可能性是让两个对象都知道代理包装,并用equals/hashcode处理它。但这会给原始类带来它不应该有的依赖项
另一种可能性是,如果不需要代理行为,则展开代理,并使用真实对象。在创建代理的上下文中,应该有如下映射:
Map<Proxy, Original> map;
Map;
您不应该到处传递JAVA代理。每个对象都必须知道,代理是传入的,因为它们可以将它们存储在激活equals和hashcode的Set实现中。一旦传递JAVA代理,使用具有这种依赖性的类就会造成污染
Java代理应该尽可能地隔离。生成Java代理的类应该是唯一使用它们的类
另一种(更常见的)可能性是使用标准代理模式,而不使用任何JAVA代理。但是在这里,你必须考虑在HASCOD/EQUALS中的代理包装,如果你将代理对象传递出去。你必须在接口的成员方法方面实现你的接口实现的<>代码>均衡器< /代码>方法。查看List#equals(Object)
是如何实现的(在javadoc中是如何描述的)。
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;
}
Map<Proxy, Original> map;