Змінюй хід війни! Допомагай ЗСУ!

Java. nameOfObject.equals(nameOfObject)

🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
Статус: Offline
Реєстрація: 26.07.2010
Повідом.: 52
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #1
Привествую. Прочитал несколько страниц, разобрался с программой, но не разобрался с одним методом до конца.

есть три класса:
суперкласс class Employee
Код:
import java.util.*;

class Employee {

    private String name;
    private double salary;
    private Date hireDay;

    Employee(String name, double salary, int year, int month, int day) {
        this.name = name;
        this.salary = salary;
        GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
        hireDay = calendar.getTime();
    }

    public String getName() { return name; }
    public double getSalary() { return salary; }
    public Date getHireDay() { return hireDay; }

    public String toString() {
        return name + " " + salary + " " + hireDay;
    }

    public boolean equals(Object otherObject) {
        if(this == otherObject) return true;
        if(otherObject == null) return false;
        if(getClass() != otherObject.getClass()) return false;

        Employee other = (Employee)otherObject;

        return name.equals(other.name)
                && salary == new Double(other.salary)
                && hireDay.equals(other.hireDay);
    }

    public int hashCode() {
        return 7 * name.hashCode() +
                11 * new Double(salary).hashCode() +
                13 * hireDay.hashCode();
    }
}
далее, его потомок class Manager extends Employee
Код:
class Manager extends Employee {

    private double bonus;

    Manager(String name, double salary, int year, int month, int day) {
        super(name, salary, year, month, day);
        bonus = 0;
    }

    public void setBonus(double bonus) { this.bonus = bonus; }

    public double getSalary() { return super.getSalary() + bonus; }

    public String toString() { return super.toString() + " " + bonus; }

    public boolean equals(Object otherObject) {
        if(!super.equals(otherObject)) return false;
        Manager other = (Manager)otherObject;
        return bonus == other.bonus;
    }

    public int hashCode() { return super.hashCode() + 17 * new Double(bonus).hashCode(); }
}
и основной класс EqualsTest
Код:
public class EqualsTest {

    public static void main(String[] args) {

        Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
        Employee alice2 = alice1;
        Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);

        Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1);

        System.out.println("alice1 == alice2: " + (alice1 == alice2));
        System.out.println("alice1 == alice3: " + (alice1 == alice3));

        System.out.println("alice1.equals(alice2): " + alice1.equals(alice2));
        System.out.println("alice1.equals(alice3): " + alice1.equals(alice3));

        System.out.println("alice1.equals(bob): " + alice1.equals(bob));

        System.out.println("bob.toString(): " + bob);

        Manager carl = new Manager("Carl Cracker", 80000, 1987, 12, 15);
        Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);

        boss.setBonus(5000);

        System.out.println("boss.toString: " + boss);

        System.out.println("carl.equals(boss):" + carl.equals(boss));

        System.out.println("alice1.hashCode(): " + alice1.hashCode());
        System.out.println("alice3.hashCode(): " + alice3.hashCode());
        System.out.println("carl.hashCode(): " + carl.hashCode());
        System.out.println("bob.hashCode(): " + bob.hashCode());

        Employee mark = new Manager("Mark", 80000, 1980, 10, 1);
        Manager kram = new Manager("Mark", 80000, 1980, 10, 1);

        System.out.println("mark.equals(kram): " + mark.equals(kram));
    }
}

Если взять отдельную строчку, например
Код:
System.out.println("alice1.equals(alice2): " + alice1.equals(alice2));
Всё понятно, вызываем метод .equals, проверяем или alice1 ссылается на тот же объект, что и alice2. Возвращаем true.
Далее, берём следующую строчку
Код:
System.out.println("alice1.equals(alice3): " + alice1.equals(alice3));
Тоже всё понятно, это разные объект, объект alice3 не нулевой, далее проверяется getClass() на идентичность класса alice1 и alice3, если они идентичны то, происходит преобразование типа alice3 и, проверяются поля. Если они одинаковые, возвращается true.

Не понятно, почему true происходит в случае
Код:
        Employee mark = new Manager("Mark", 80000, 1980, 10, 1);
        Manager kram = new Manager("Mark", 80000, 1980, 10, 1);

        System.out.println("mark.equals(kram): " + mark.equals(kram));

Почему getClass() сравнивая разные типы Manager и Employee выдаёт true?
Код:
if(getClass() != otherObject.getClass()) return false;
Когда я спрашивал про принцип постановки то, там надо было сделать преобразование для установки бонуса менеджеру типа Employee ((Manager)employee[1]).setBonus(500);

или пробежаться по массиву и проверить не является ли элемент экземпляром.
Код:
if(employee[i] instanceof Manager)
        ((Manager)employee[i]).setBonus(500;


что-то я совсем запутался уже. :D


P.S> Спасибо за Ваше время!



может в подклассе при переопределении метода equals(Object otherObject)
Код:
if(getClass() != otherObject.getClass()) return false;
нужно добавить строку, типа:
Код:
if(ohterObject instanceof Employee) return false;

тогда сравнивая два объекта Manager(...) с разными типами метод будет возвращать значение false;

Правильно? :confused:
 
Останнє редагування:
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #2
Почему getClass() сравнивая разные типы Manager и Employee выдаёт true?

а что ты хотел чтобы вернул getClass для ?

Код:
        Employee mark = new Manager("Mark", 80000, 1980, 10, 1);
        Manager kram = new Manager("Mark", 80000, 1980, 10, 1);
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #3
Kompot

Речь не идёт о том, чего хочу я.
Я спрашиваю, почему он возвращает true? У двух переменных разный класс(тип). Переменная mark типа Employee, переменная kram типа Manager.

Так, например, Вы не сможете использовать метод и установить бонус для объекта mark.setBonus(500), а для kram.setBonus(500). Потому что переменная mark другого типа.
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #4
для того чтобы все это полностью понять. Нужно понять как программа работает с памятью.
1. Разберитесь что означает и делает ключевое слово new
2. Что именно делает метод equals

Ответите на эти два вопроса, и сразу ответите на свой вопрос
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #5
kosyak

1) Слово new создаёт экземпляр класса Manager.
2) метод equals сравнивает объекты mark и kram.
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #6
с таким уровнем ответов на два вопроса, на ваш вопрос, ответ будет на таком же уровне - "потому что так".

Даже и так, вы уже сами ответили
Слово new создаёт экземпляр класса Manager.
Вы создали два разных экземпляра?
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #7
kosyak

А какой должен был быть уровень ответа?

p.s. т.е. getClass() смотрит на класс экземпляра, а не на тип переменной? Я не понял именно это.
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #8
На уровне вашего вопроса.

1) Что означает "создает экземпляр" ?
2) По каким критериям сравниваются объекты ?
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #9
Не понятно, почему true происходит в случае
Код:
        Employee mark = new Manager("Mark", 80000, 1980, 10, 1);
        Manager kram = new Manager("Mark", 80000, 1980, 10, 1);

        System.out.println("mark.equals(kram): " + mark.equals(kram));

Почему getClass() сравнивая разные типы Manager и Employee выдаёт true?

ну вообщето в приведенном тобой-же фрагменте, черным по белому написано что переменным mark и kram присваиваются объекты одно и того-же типа - Manager ;)
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #10
kosyak

1) Создание объекта по "шаблону" класса, в котором описаны члены класса (поля и методы).
2) В моём случае?
Код:
// ссылаются ли две переменные на один и тот же объект       
if(this == otherObject) return true;
// является ли объект нулевым
if(otherObject == null) return false;
// сравниваются классы объектов
if(getClass() != otherObject.getClass()) return false;


Employee other = (Employee)otherObject;
// сравниваются по полям объекта.
        return name.equals(other.name)
                && salary == new Double(other.salary)
                && hireDay.equals(other.hireDay);

Klez

Не, я неправильно понял getClass()

P.S. Просто, я запутался окончательно, с этими классами, типами, переменными, ссылаются и т.д. :D
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #11
1) прочитайте еще раз первое предложение моего первого поста
2) Да, что делает equals?
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #12
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #13
1) для того чтобы все это полностью понять. Нужно понять как программа работает с памятью.
Ок, объясните, пожалуйста, как работает программа с памятью.

2) метод public boolean equals(Object otherObject) получает в качестве аргумента (или параметра) объект, сравнивает этот аргумент с текущим объектом и если они равны (адрес объекта), возвращает true или если неравны false; Как сравнивать это определяет программист, т.е. если надо сравнить по классу или полям, нужно переопределять метод.

Код:
Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
        Employee alice2 = alice1;
        
        System.out.println("alice1 == alice2: " + (alice1 == alice2));
        
        System.out.println("alice1.equals(alice2): " + alice1.equals(alice2));
В данном примере две переменные ссылаются на один и тот же объект. Метод по умолчанию даст true.

Klez

Да, запутался.
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #14
== и equals делают две разные вещи

== - сравнивает ссылки
equals - сравнивает хэши объектов.
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #15
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #16
ух.

Рассмотрим ваш пример.

Employee mark = new Manager("Mark", 80000, 1980, 10, 1);
Manager kram = new Manager("Mark", 80000, 1980, 10, 1);

new Manager("Mark", 80000, 1980, 10, 1) инициализирует в памяти последовательность байт представляющая объект Manager (к примеру ad 04 6e 4f 00 df ff bc 67 39 00 00 00 итд)
И вы присваиваете mark указатель на вышеуказанную последовательность байт.

Затем вы инициализируете в памяти последовательность байт представляющая опять же объект Manager (к примеру ad 04 6e 4f 00 df ff bc 67 39 00 00 00 итд).

метод equals является методом суперкласса Object значит этот метод имеют все объекты.
equals берет последовательности байт на которые указывают ваши ссылки, делает их хэш и сравнивает.
Как вы думаете хэши будут разные у этих двух строк?
ad 04 6e 4f 00 df ff bc 67 39 00 00 00
ad 04 6e 4f 00 df ff bc 67 39 00 00 00
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #17
equals - сравнивает хэши объектов.
equals делает то, что ему написано.
здесь он определен.
*да, хэши тоже

beerofeel,
есть переменные - они имеют тип (могут хранить [указатель на] объекты некого типа-класса)
есть собственно объект - экземпляр класса, он же кусок выделенной памяти, который содержит поля класса и т.п.
есть класс - он же тип. описывает поля и методы .

переменная определенного типа может содержать как объекты этого типа, так и объекты классов наследников его.
от того, что на объект указывает переменная "не совсем того же типа" - сам объект не изменяется.
 
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #18
kosyak

О! Объяснили, доступно! Я понял. :D Спасибо большое.

P.S. секунду. Но в моём случае, метод equals переопределён и два объекта проверяются по полям, поэтому они получаются равными. Вот нашёл программку. Почему, тогда здесь объекты считаются разными?
АААААААААААААААААААА... :eek: чё-то я совсем запутался.
Код:
public class Student
{
  private int student_id;

  public Student(int student_id)
  {
    this.student_id = student_id;
  }

  public static void main(String[] args)
  {
    Student s1 = new Student(8888);
    Student s2 = new Student(8888);

    if(s1.equals(s2))
    System.out.println("Они равны!");
    else
    System.out.println("Они не равны!");
  }
}

Объекты получаются разными.

Hisp

Да, спасибо! Логика есть! Главное понять где ноги, а где руки. :D
Получается, что преобразование типа переменной суперкласса, которая ссылается на объект подкласса, это полиморфизм - и я перепутал с ним.
Код:
public boolean equals(Object otherObject) {
if(getClass() != otherObject.getClass()) return false;
getClass() не имеет отношения к типу переменной, а берёт для сравнения классы объекта. :eyecrazy:
 
Останнє редагування:
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #19
Вот нашёл программку. Почему, тогда здесь объекты считаются разными?
АААААААААААААААААААА... :eek: чё-то я совсем запутался.
Код:
    Student s1 = new Student(8888);
    Student s2 = new Student(8888);

    if(s1.equals(s2))
    System.out.println("Они равны!");
    else
    System.out.println("Они не равны!");

Объекты получаются разными.

не слушай косяка, у него каша в голове :) дефолтный equals возвращает true, если у объектов равны значения hashCode. А hashCode по дефолту возвращает identity объекта, т.е. уникальный идентификатор.
У двух разных объектов, с одинаковым содержимым, identity будет естественно разным, потому что это два разных объекта. Соответственно equals будет возвращать false

Да, спасибо! Логика есть! Главное понять где ноги, а где руки. :D
Получается, что преобразование типа переменной суперкласса, которая ссылается на объект подкласса, это полиморфизм - и я перепутал с ним.

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

Не знаю как в java, в C# можно вместо типа переменной писать просто var. В этом случае компилятор сам разбирается какой тип объекта лежит в переменной.
Т.е. твой пример можно переписать так:
Код:
    var s1 = new Student(8888);
    var s2 = new Student(8888);

    if(s1.Equals(s2))
       Console.WriteLine("Они равны!");
    else
       Console.WriteLine("Они не равны!");



getClass() не имеет отношения к типу переменной, а берёт для сравнения классы объекта. :eyecrazy:

тип переменной просто указывает компилятору что ты предполагаешь что в этой переменной будет храниться объект такого-то класса или класса-наследника. Таким образом компилятор может проверить что ты не ошибся на этапе компиляции.
 
Останнє редагування:
  • 🟢 11:57 Відбій тривоги в м. Харків та Харківська територіальна громада.Слідкуйте за подальшими повідомленнями.#м_Харків_та_Харківська_територіальна_громада
  • #20
Klez

Вот две страницы связаны с полиморфизмом.

⚠ Тільки зареєстровані користувачі бачать весь контент та не бачать рекламу.
⚠ Тільки зареєстровані користувачі бачать весь контент та не бачать рекламу.


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

1) переопределение метода в подклассе (замещение метода).
2) объект подкласса можно использовать вместо любого объекта суперкласса называется принцип постановки.
например: Объект подкласса Manager можно присвоить переменной суперкласса

Employee e;
e = new Employee(...);
e = new Manager(...)*

3) переменная типа суперкласса может ссылаться как на объект суперкласса, так и на объект любого подкласса:

Manager manager = new Manager(...);
Employee[] employee = new Employee[3];
employee[0] = manager;
employee[1] = new Manager(...);


Что я должен был понять в полиморфизме, хрен его знает. :D
 
Назад
Зверху Знизу