Реализация hashCode () по умолчанию для объектов Java
Я пытался понять хэш-код () для объекта Java и увидел следующий код для метода hashCode () объекта Java:
package java.lang;
public class Object {
// Some more code
public native int hashCode();
// Some other code
}
Теперь мы знаем, что если мы создаем класс, он неявно расширяет класс объектов, и для этого я написал примерный пример:
package com.example.entity;
public class FirstClass {
private int id;
private String name;
// getters and setters
}
Таким образом, этот класс, а именно: FirstClass, будет неявно расширять класс Object.
Основной класс:
package com.example.app.main;
import com.example.entity.FirstClass;
public class MainApp {
public static void main(String[] args) {
FirstClass fs = new FirstClass();
fs.setId(1);
fs.setName("TEST");
System.out.println("The hasCode for object fs is " + fs.hashCode());
}
}
Поскольку FirstClass расширяет Object класс неявно, следовательно, он будет иметь Object классы ' hashCode() метод.
Я вызвал hashCode() на FirstClass объекте , и поскольку я не переопределил hashCode(), теоретически он должен вызвать Object класс hashCode().
Мое сомнение:
Поскольку класс объектов не имеет никакой реализации, как он может вычислить хэш-код для любого объекта?
В моем случае, когда я запускал программу, хэш-код, который она возвращала, был 366712642.
Может ли кто - нибудь помочь мне понять это?
3 ответов:
Хотя здесь есть некоторые ответы, утверждающие, что реализация по умолчанию основана на "памяти", это явно неправильно. Это не так уже много лет.
В java-8 вы можете сделать:
java -XX:+PrintFlagsFinal | grep hashCode, чтобы получить точный алгоритм, который используется (
5по умолчанию).0 == Lehmer random number generator, 1 == "somehow" based on memory address 2 == always 1 3 == increment counter 4 == memory based again ("somehow") 5 == read belowПо умолчанию (
5) он использует алгоритм Marsaglia XOR-Shift, который не имеет ничего общего с памятью.Это не очень трудно доказать, если вы сделаете:
System.out.println(new Object().hashCode());Несколько раз, в новой виртуальной машине все время-вы получите одно и то же значение, поэтому Marsaglia XOR-Shift начинается с семени (всегда одно и то же, если только какой-то другой код не изменяет его) и работает от этого.
Но даже если вы переключаетесь на некоторый хэш-код, основанный на памяти, и объекты потенциально перемещаются (вызовы сборщика мусора), как вы гарантируете, что тот же хэш-код будет взят после того, как GC переместил этот объект? Подсказка: indentityHashCode и заголовки объектов.
Вы все неправильно поняли:
public native int hashCode();Не означает, что нет реализации. Это просто означает, что метод реализован вродной aka C/C++ части JVM. Это означает, что вы не можете найти исходный код Java для этого метода. Но где-то в JVM все еще есть некоторый код, который вызывается всякий раз, когда вы вызываете
hashCode()на каком-то объекте.И как объясняет другой ответ: что реализация "default" использовала адрес" memory" базовые объекты. Дело в том, что использование java означает, что нет знания "адресов памяти". Имейте в виду: JVM написан на C/C++ - и реальное управление памятью происходит в этих собственных частях JVM.
Другими словами: Вы не можете написать Java-код, который сообщает вам о "собственном адресе памяти" объекта.Но как ясно из другого ответа Юджина: хэш, связанный с "расположением памяти", - это дело прошлого.
Реализация хэш-кода по умолчанию в классе объектов - это адрес памяти объекта в шестнадцатеричном формате. JVM призывает к реализации этого.
Некоторые полезные ссылки:
Https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
Comments