使用JDK动态代理实现equals() [英] Implementing equals() with JDK Dynamic Proxies

查看:309
本文介绍了使用JDK动态代理实现equals()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是有史以来第一次,我必须使用标准的JDK动态代理来实现自己的代理类.除了一个细节:equals(...)方法之外,它工作得还不错.

For the first time ever, I have to implement my own proxy classes using the standard JDK Dynamic Proxy. It works fairly well, except for one detail: the equals(...) method.

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

Let's assume that we have a simple Interface like this, which we want to proxy:

public interface MyInterface {
    public String getID();
    public void setID(String id);
}

...,我们的实现如下所示(带有生成的hashCode()equals的标准Java Bean):

... and our implementation looks like this (standard Java Bean with generated hashCode() and 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;
    }
}

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

The problem is, that when I create a proxy, the equals(...) method is no longer symmetric:

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

本文.

我的问题是:如果我希望所有四个相等"的案例都得到实现,那么什么是最好的(即最安全,侵入性最小)的解决方法?

My question is: if I want all four "equals" cases to deliver true, what's the best (i.e. safest and least intrusive) way to go about it?

推荐答案

您将找到一个可行的解决方案.但是存在一个巨大的问题:

You will find a solution that will work. But there is a huge problem:

要相互比较的两个对象都必须知道代理包装.

Both objects to compare with each other have to be aware of Proxy-Wrapping.

JAVA在技术上下文中做到了正确,即代理与其他对象均被平等地处理.但是...

JAVA does it right in the the technical context, that Proxies are handled equally to other objects. But...

当我偶然发现这个问题时,我的个人观点是现在:JAVA应该引入对代理的内置支持,一旦调用hashcode和equals,内部就会对其进行解包.

My personal opinion as I stumbled over this issue was and is right now: JAVA should introduce built-in support for proxies, that internally are unwrapped as soon as hashcode and equals are called.

代理对于常规"实现应透明.无论您是否拥有代理人或原始人,您都不应打扰.但是JAVA用这种方式做错了.

Proxies should be transparent to the "normal" implementation. You should not bother about wether you have a proxy or the original. But JAVA does it wrong in this way.

一种可能性是使两个对象都知道Proxy-Wrapping,并以equals/hashcode对其进行处理.但这会使原始类充满了它不应该具有的依赖项.

One possibility is to make both objects aware of Proxy-Wrapping and handle it in equals/hashcode. But this floods the original class with a dependency that it should not have.

另一种可能性是,如果不需要代理行为,则可以打开代理包装,而应使用真实对象.在您创建代理的上下文中,您应该具有这样的地图:

Another possibility is to unwrap the Proxy if proxy behaviour is not needed and use the real object instead. In the context you create the Proxy you should have a Map like this:

Map<Proxy, Original> map;

您不应四处传递JAVA代理.每个对象都必须知道传入了一个代理,因为它们可以将它们存储在Set-Implementations中,在该Set-Implementations中,equals和hashcode被激活.绕过JAVA代理后,您便会使用具有这种依赖关系的类进行污染.

You should not pass JAVA proxies around. Every object has to know, that a proxy was passed in as they may store them in Set-Implementations where equals and hashcode are activated. As soon as you pass around JAVA Proxies you pollute using classes with this dependency.

Java代理应该尽可能地隔离.产生Java代理的类应该是唯一使用它们的类.

Java Proxies should be as isolated as possible. The class that produces Java Proxies should be the only class that uses them.

另一种可能性(镀上更多样)是使用没有任何JAVA代理的标准代理模式.但是再说一遍:如果传递代理对象,则还必须考虑哈希码/等号中的Proxy-Wrapping.

Another (more boiler-plated) possibility is to use the standard proxy pattern without any JAVA proxies. But here again: You have to consider Proxy-Wrapping in hashcode/equals as well if you pass your proxied objects around.

这篇关于使用JDK动态代理实现equals()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆