Роль оператора == в Java, проверяющего адрес памяти - PullRequest
0 голосов
/ 03 февраля 2019

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

Сущность Student: открытый класс 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;
    }


}

Ввод Duplicates в 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);
    }
}

enter image description here enter image description here enter image description here enter image description here

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

Ответы [ 3 ]

0 голосов
/ 03 февраля 2019

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

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

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

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

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

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

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

0 голосов
/ 03 февраля 2019

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

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

0 голосов
/ 03 февраля 2019

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

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

stringops.Student@955a0720

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

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

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

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

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

...