Я пробую некоторый код вокруг объектного равенства в Java. Поскольку я читал где-нибудь
hashCode()
число, которое сгенерировано путем применения хеш-функции. Хеш-функция может отличаться для каждого объекта, но может также быть тем же. На уровне объектов это возвращает адрес памяти объекта.
Теперь, у меня есть программа программы, которую я запускаю 10 раз, последовательно. Каждый раз, когда я запускаю программу, я получаю то же значение как хэш-код.
Если hashCode()
функционируйте возвращает ячейку памяти для объекта, каким образом Java (JVM) хранит объект в том же адресе памяти в последовательных выполнениях?
Можно ли дать мне некоторое понимание и представление по этой проблеме?
Программа, которую я запускаю для тестирования этого поведения, ниже:
public class EqualityIndex {
private int index;
public EqualityIndex(int initialIndex) {
this.index = initialIndex;
}
public static void main(String[] args) {
EqualityIndex ei = new EqualityIndex(2);
System.out.println(ei.hashCode());
}
}
Каждый раз, когда я запускаю эту программу, возвращенное значение хэш-кода 4072869
.
почему Java (JVM) сохраняет объект по одному и тому же адресу памяти при последовательных запусках?
Почему бы и нет? Программы, не относящиеся к ядру, никогда не работают с абсолютными адресами памяти, они используют виртуальную память, где каждый процесс получает собственное адресное пространство. Поэтому нет ничего удивительного в том, что детерминированная программа будет размещать данные в одном и том же месте при каждом запуске.
Функция hashCode ()
должна возвращать то же значение для одного и того же объекта при одном выполнении. Необязательно возвращать одно и то же значение для разного исполнения. См. Следующие комментарии, извлеченные из класса Object
.
Общий контракт hashCode таков:
Каждый раз, когда он вызывается на одном и том же объекте более одного раза в течение выполнение приложения Java, метод hashCode должен последовательно возвращать одно и то же целое число при отсутствии информации используется в равных сравнениях объекта. Это целое число не обязательно должно оставаться непротиворечивым после одного выполнения приложение к другому исполнению того же приложения.
Я выполнил ваш код несколько раз.Вот мой результат
1935465023
1425840452
1935465023
1935465023
1935465023
1925529038
1935465023
1935465023
Одно и то же число повторяется несколько раз. Но это не значит, что они всегда одинаковы. Предположим, конкретная реализация JVM ищет первый свободный слот в памяти. тогда, если вы не запускаете никаких других приложений, шансы разместить объект в том же слоте высоки.
Как я уже где-то читал: " ... На уровне объекта он возвращает адрес памяти объекта."
Это утверждение неверно или, в лучшем случае, является чрезмерным упрощением.
Это утверждение относится к реализации по умолчанию Object.hashCode()
, которая возвращает то же значение, что и System.identityHashcode(Object)
.
В Javadoc для Object.hashCode()
сказано следующее:
Насколько это возможно на практике, метод hashCode, определенный в классе Object, возвращает разные целые числа для разных объектов. (Обычно это реализуется путем преобразования внутреннего адреса объекта в целое число, но такая техника реализации не требуется языком программирования JavaTM).
и это:
Всякий раз, когда метод hashCode вызывается для одного и того же объекта более одного раза во время выполнения Java-приложения, он должен последовательно возвращать одно и то же целое число, при условии, что никакая информация, используемая в сравнениях equals на объекте, не изменена.
Фактически, значение хэш-кода идентификации обычно основано на машинном адресе объекта когда метод впервые вызывается для объекта. Значение хранится в скрытом поле в заголовке объекта. Это позволяет возвращать один и тот же хэш-код при последующих вызовах... даже если GC за это время переместил объект.
Обратите внимание, что если значение хэш-кода идентичности изменится за время жизни объекта, это нарушит контракт для hashcode()
и будет бесполезно в качестве хэш-кода.
Что ж, объекты вполне могут оказаться в одном и том же месте виртуальной памяти. Ничего противоречащего этому. Суть в том, что вам все равно все равно. Если хэш-код реализован так, чтобы возвращать что-то, связанное с адресом внутреннего хранилища (нет никакой гарантии!), Вы в любом случае ничего полезного не сможете сделать с этой информацией.
hashCode может быть переопределен используемым классом, в JavaDoc для Object.hashCode() говорится, что он '... обычно реализуется путем преобразования внутреннего адреса объекта в целое число...', так что фактическая реализация может зависеть от системы. Обратите внимание также на третий пункт в JavaDoc о том, что два неравных объекта не обязаны возвращать разные хэш-коды.
for (int i=0; i < 10; i++) {
System.out.println("i: " + i + ", hashCode: " + new Object().hashCode());
}
prints:
i: 0, hashCode: 1476323068
i: 1, hashCode: 535746438
i: 2, hashCode: 2038935242
i: 3, hashCode: 988057115
i: 4, hashCode: 1932373201
i: 5, hashCode: 1001195626
i: 6, hashCode: 1560511937
i: 7, hashCode: 306344348
i: 8, hashCode: 1211154977
i: 9, hashCode: 2031692173
Если два объекта равны, они должны иметь одинаковые хэш-коды. Таким образом, пока вы не создаете простые экземпляры Object
, каждый раз, когда вы создаете объект с одинаковым значением, вы будете получать один и тот же хэш-код.
Какие типы объектов вы создаете? Это особый вид объекта, например String (например). Если это особый вид, класс уже может переопределить метод hashCode () и вернуть его вам. В этом случае то, что вы получаете, больше не является адресом памяти.
а также какие значения вы получаете, вы уверены, что это адрес памяти?
Итак, отправьте дополнительный код для получения более подробной информации