Роль оператора == в Java, проверяющем адрес памяти

До сегодняшнего дня я считал, что два объекта с одинаковым хэш-кодом означают, что оба они имеют одинаковую ячейку памяти. Но приведенный ниже фрагмент кода рассказывает совсем другую историю:

Студенческая организация: открытый класс Student реализует Comparable {

int id;
int marks;
String Subject;

public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public int getMarks() {
    return marks;
}
public void setMarks(int marks) {
    this.marks = marks;
}
public String getSubjects() {
    return Subject;
}
public void setSubject(String subject) {
    Subject = subject;
}

public Student() {

}
public Student(int id, String subject, int marks) {
    super();
    this.id = id;
    this.marks = marks;
    Subject = subject;
}
@Override
public int compareTo(Student o) {
    if (this.getId()>(o.getId()))
    return 1;

    if (this.getId()<(o.getId()))
    return -1;

    return 1;
}

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((Subject == null) ? 0 : Subject.hashCode());
        result = prime * result + id;
        result = prime * result + marks;
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (Subject == null) {
            if (other.Subject != null)
                return false;
        } else if (!Subject.equals(other.Subject))
            return false;
        if (id != other.id)
            return false;
        if (marks != other.marks)
            return false;
        return true;
    }


}

Ввод дубликатов в Hashmap, чтобы проверить, работает ли переопределение equals и hashcode():

public class TestHashSet3 {

    static Student s1;
    static Student s2;
    static Student s3;

    public static void main(String[] args) {
        setStudent();
        testSet();
        testMap();
 }

    static void testMap() {
        Map<Student, String> empMap = new HashMap<>();
        empMap.put(s1, "Arun");
        empMap.put(s2, "Shivam");
        empMap.put(s3, "Varun");
        System.out.println("HashMap executed = ");
        for (Map.Entry<Student, String> obj : empMap.entrySet()) {
            System.out.println(obj  +  " ");
        }
    }

    static void testSet() {
        Set<Student> set = new HashSet<>();
        set.add(s1);
        set.add(s2);
        set.add(s3);
        System.out.println("HashSet executed = ");
        for (Student student : set) {
            System.out.println(student  +  " ");
        }

    }

    static void setStudent() {
        s1 = new Student(124, "Maths", 50);
        s2 = new Student(124, "Maths", 50);
        s3 = new Student(124, "Maths", 50);
    }
}

Роль оператора == в Java, проверяющем адрес памятиРоль оператора == в Java, проверяющем адрес памятиРоль оператора == в Java, проверяющем адрес памятиРоль оператора == в Java, проверяющем адрес памяти

На последнем снимке экрана мы видим, что это ==obj оказывается ложным. Но почему ?

Пожалуйста, публикуйте свой код, а не скриншоты кода.

Zephyr 02.02.2019 22:22

мы предпочитаем текст скриншотам

Marged 02.02.2019 22:23

добавлен код, пожалуйста, проверьте сейчас

ASharma7 02.02.2019 22:30

нет, вы неправильно усвоили урок (математики): с одним и тем же хэш-кодом другой объект/ввод равен всегдавозможный (по определению «хэш-код»). хеш-код")... ваш хеш-код "плохой" в этих терминах.

xerx593 02.02.2019 22:30

"Местоположение в памяти" не должно быть концепцией, затрагивающей большую часть программирования на Java. Ближайшая концепция, которая вам определенно нужна, это «это две ссылки на один и тот же объект или на разные объекты?». И, конечно же, как уже умело указано, одинаковые хэш-коды, конечно, не означают, что они являются одним и тем же объектом.

user10762593 03.02.2019 02:48
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
5
851
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Ну, это не совсем так, что hashCode() всегда возвращает адрес памяти. В вашем конкретном случае вы перезаписываете функцию, чтобы в основном вернуть хэш-код ссылки Subject.

Ваша оценка показывает следующий вывод:

stringops.Student@955a0720

что может немного сбивать с толку, поскольку на самом деле это НЕТ адрес пустой памяти, а вызов метода toString() вашего объекта.

Посмотрите, как Java реализуетtoString:

getClass().getName() + '@' + Integer.toHexString(hashCode())

Итак, на самом деле эти два объекта имеют разные области памяти, но поскольку вы перезаписываете hashCode(), вы не сможете их увидеть. Кроме того, нет способа перезаписать то, как Java выбирает адрес памяти объекта (за исключением, может быть, некоторых хаков), но, тем не менее, два объекта не могут иметь один и тот же адрес.

Пожалуйста, в следующий раз включите больше текста вместо скриншотов, чтобы повысить доступность поиска вашего вопроса для других.

Таким образом, окончательный тест, чтобы узнать, находятся ли два объекта в одной и той же ячейке памяти, заключается в проверке (obj1 == obj2) ???

ASharma7 02.02.2019 22:40

да, так как этот оператор создан специально для этого варианта использования

ggradnig 02.02.2019 22:43

только один объект может находиться одновременно по одному адресу памяти. Таким образом, только если это один и тот же объект, а не похожий объект (что может быть обнаружено методом equals), тогда только == вернет true

nits.kk 02.02.2019 22:43

Спасибо ребята за помощь!!

ASharma7 02.02.2019 22:44

hashcode — это значение типа int, возвращаемое методом hascode().

Object.java определяет hascode(), и каждый класс java является подклассом Object.java, поэтому каждый класс наследует его.

Разработчик конкретного класса решает, хочет ли он его переопределить. Разработчик класса может выбрать (хотя и плохая практика) повторный запуск одного и того же постоянного значения int для всех объектов класса.

Обычно hascode зависит от значения одного или нескольких свойств объекта. Несмотря на то, что разработчик может изо всех сил стараться вернуть уникальный хэш-код, но все же (коллизия хэш-кода) два разных объекта могут получить один и тот же хэш-код.

В каждый момент времени одна ячейка памяти может быть назначена только одному объекту.

Хэш-код двух разных объектов (находящихся по двум разным адресам в памяти) может быть одинаковым или может отличаться

Также связанная концепция: контракт равных и метод hascode. В нем говорится, что если два объекта имеют значение true, возвращаемое вызовом equals, то оба объекта должны иметь одинаковый хэш-код. Обратите внимание, что это определенный контракт, но разработчик должен разработать класс и написать метод хэш-кода для соблюдения контракта. Плохая реализация может привести к тому, что два объекта, возвращающие метод true for equals, будут возвращать разные хэш-коды.

Вы только что правильно определили, что два разных объекта — то есть два объекта с разными адресами памяти — действительно могут иметь один и тот же хеш-код. Правила заключаются в том, что если два объекта равны по методу .equals(), то они должны создавать один и тот же хэш-код. Помимо этого и общей идеи о том, что «разные объекты должны пытаться иметь разные хеш-коды», нет требования, чтобы объекты в разных местах хэшировались по-разному.

Но это хорошо. Например, два разных объекта String, каждый из которых имеет одинаковую последовательность символов, должны интуитивно иметь одинаковый хеш-код, чтобы HashMap<String, T> мог правильно искать строки. Таким образом, предоставление объекта String, отличного от того, который используется в качестве ключа, но с тем же логическим значением, будет работать правильно; все String с одинаковым хешем последовательности символов в одно и то же место.

Другие вопросы по теме