Подскажите пожалуйста, должен ли Hashcode объекта измениться если его поля изменились?
Ни фига не должен, смотрим сюда:
public class HelloWorld {
public static void main(String[] args) {
//создаем объект
MyMutable myMutable = new MyMutable(1, "Hello");
System.out.println("intValue="+myMutable.getIntValue()+", stringValue="+myMutable.getStringValue()+", hashcode="+myMutable.hashCode());
//мутируем (меняем) его свойства
myMutable.setIntValue(2);
myMutable.setStringValue("World!");
//проверяем hashCode()
System.out.println("intValue="+myMutable.getIntValue()+", stringValue="+myMutable.getStringValue()+", hashcode="+myMutable.hashCode());
}
}
class MyMutable {
private int intValue;
private String stringValue;
public MyMutable(int intValue, String stringValue) {
this.intValue=intValue;
this.stringValue=stringValue;
}
public void setIntValue(int intValue) {
this.intValue=intValue;
}
public int getIntValue() {
return this.intValue;
}
public void setStringValue(String stringValue) {
this.stringValue=stringValue;
}
public String getStringValue() {
return this.stringValue;
}
}
Вывод:
intValue=1, stringValue=Hello, hashcode=1829164700
intValue=2, stringValue=World!, hashcode=1829164700
Специально ввел 2 разных поля, все равно при их изменении hashCode() не пересчитывается и остается прежним.
Update
по следам дискуссии в комментариях:
1) В дефолтной реализации hashCode() он не будет меняться при мутации объекта
2) Чтобы он менялся необходимо переопределять hashCode(), например для приведенного примера приблизительно так:
public int hashCode() {
return super.hashCode()+
this.intValue+
((this.stringValue==null?0:this.stringValue.hashCode());
}
https://habr.com/post/168195/
Одинаковые объекты — это объекты одного класса с одинаковым содержимым полей.
Если объекты одинаковые, то и хеш-коды одинаковые (но не наоборот, см. правило 3).
Да, должен. Вот что по этому поводу пишут в документации:
The general contract of hashCode is:
Это следует из второго пункта и выделенной части первого. Но стоит иметь ввиду, что реализация по умолчанию метода hashCode этим принципам не следует, поэтому её всегда надо переопределять.
Все просто:
Если при описании своего объекта вы не переопределяете метод hashcode, то при его инициализации(вызов new) ему присваивается идентификационный хеш - hash по умолчанию. Делается это при помощи стандартного нативного метода.
В этом случае поля вашего объекта никак не влияют на формирование hashcode, соответственно любые изменения этих полей не приведут к изменению hashcode. Стоит учитывать, что создание нового аналогичного объекта не гарантирует совпадение hashcode
Если же вы явно переопределили метод hashcode и вычисление hash - объекта завязали на значение своих полей, то при их изменении hashcode так же изменится
Правильнее было бы использовать примерно такую модель, коль вы решили использовать собственный калькулятор хеша:
public class Test
{
private int _a;
private int _b;
private int _c;
public Test(int a, int b, int c)
{
_a = a;
_b = b;
_c = c;
}
@Override
public int hashCode()
{
return _a ^ _b ^ _c;
}
}
И не обязательно возвращать сгенерированный самой JVM хешкод объекта при запросе через super.hashcode(), если изменилось какое-то условие. На мой взгляд это моветон.
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости