提问人:maddy man 提问时间:6/26/2016 最后编辑:Communitymaddy man 更新时间:6/26/2016 访问量:105
当预期 Immutable 对象时,可变子类对象如何导致问题的代码示例
Code Example for how a Mutable subclass object can cause issue when Immutable object is expected
问:
我一直在问这个问题:为什么人们会在 Java 中声明一个不可变的类 final?
我理解这个答案,但需要一个代码示例。
我写了它,但有一些疑问,如果有人能帮忙,将不胜感激。
public class Immutable {
private final int value;
public Immutable(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public boolean equals(Object obj) {
return (obj instanceof Immutable
&& getValue() == ((Immutable) obj).getValue());
}
public int hashCode() {
int hash = 1;
hash = hash * 31 + value;
return hash;
}
}
public class Mutable extends Immutable {
private int realValue;
public Mutable(int value) {
super(value);
realValue = value;
}
public int getValue() {
return realValue;
}
public void setValue(int newValue) {
realValue = newValue;
}
}
// test class main()
Mutable key = new Mutable(30);
Hashtable<Immutable, String> ht = new Hashtable<Immutable,String>();
ht.put(new Immutable(10), "10");
ht.put(new Immutable(20), "20");
ht.put(key, "30");
System.out.println("Hashcode : "+key.hashCode()+", \tKey : "+key.getValue()+" => Value : "+ht.get(key));
key.setValue(40);
System.out.println("Hashcode : "+key.hashCode()+", \tKey : "+key.getValue()+" => Value : "+ht.get(key));
Output :
Hashcode : 61, Key : 30 => Value : 30
Hashcode : 61, Key : 40 => Value : 30
我无法将给出的答案与此代码联系起来。
答:
0赞
dpr
6/26/2016
#1
您的代码正在正常工作,因为您的方法直接使用类中的最终字段,而不是使用字段的 getter。使用 from 方法时,此字段不会更改,因为此方法仅适用于该字段。hashCode
value
Immutable
setValue
Mutable
realValue
如果更改为hashCode
public int hashCode() {
int hash = 1;
hash = hash * 31 + getValue(); // use getter here
return hash;
}
您将观察到此答案中描述的不良行为。
需要注意的是,您的代码实际上违反了等价合约。由于两个实例可能彼此相等,但具有不同的哈希码......Mutable
评论
0赞
maddy man
6/26/2016
我将equals方法更新为:public boolean equals(Object obj) { return (obj instanceof Immutable && obj.hashCode() == this.hashCode() && getValue() == ((Immutable) obj).getValue()); }
0赞
dpr
6/27/2016
这将履行等价合同。但是,这并不是真正的最佳实践。考虑阅读此问题/答案,了解如何实现正确的等于和哈希码方法。
评论