问题描述
|
考虑以下接口:
public interface Listenable {
void listen();
}
考虑以下实现:
public class Listener implements Listenable {
public void listen() {
System.out.println(\"I am listening\");
}
}
现在,我正在通过RMI进行远程处理,并将此类的实例传递给服务器(可能不确定那里是否出现了一些黑魔法代理)。
到目前为止,我唯一能够发明的解决方案,而且不得不说它很愚蠢,是将以下代码添加到Listener类:
public class Listener implements Listenable {
private double id;
private Random rand = new Random();
public Listener() {
this.id = rand.nextDouble();
}
public void listen() {
System.out.println(\"I am listening\");
}
public int hashCode() { ... } // calculate from id
// same for equals - compare by id
}
这通常是可行的,但是我们都知道这是多么的邪恶:/应该如何处理这种情况?
更新:
Stanard equals对我不起作用,因为实例位于不同的VM上(我提到了远程处理),因此它无法工作。毕竟,我将需要一些状态变量,或者提出一些有益的方法来比较远程VM上的此类。很抱歉给您带来混乱。
解决方法
使侦听器成为枚举单例:
public enum Listener implements Listenable {
INSTANCE;
public void listen() {
System.out.println(\"I am listening\");
}
}
这样一来,只有一个instance4ѭ实例,并且保证相等。
您可能不想暴露这样的事实,您为此使用了ѭ5,甚至侦听器根本就是单身。您可以做的是使用静态方法(例如,称为Listenables
)使该枚举成为某个类的私有内部枚举,并通过静态方法公开此实现:
public static Listenable printingListenable() {
return Listener.INSTANCE;
}
, IMHO对象的相等性由其状态的相等性定义。如果对象不具有任何状态(可以说不应将其称为对象,但这是不同的说法),则该对象的所有实例在逻辑上都是相等的。因此,请勿打扰并写下:
public boolean equals(Object obj) {
return obj instanceof Listener;
}
public int hashCode() {
return 0;
}
, 由于侦听器是完全无状态的,因此出于许多实际目的,可以将不同的实例视为同一身份。简而言之,类本身将确定身份。那么呢:
public boolean equals(Object obj) {
return obj!=null&&obj.getClass().equals(this.getClass());
}
public int hashCode() {
return 0;
}
}
我担心ѭ10,因为子类可能不会被视为同一对象。
, 如果对象没有任何状态,则它们都应相等。为什么需要区分它们?