Как Spring различает два объекта, для которых метод equals() возвращает true?

«Как Spring различает два объекта, для которых метод equals() возвращает true?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Spring (и Java в целом) различает такие объекты по их идентичности (identity), а не только по логическому равенству.

1. В контексте бинов Spring:

  • Синглтоны (по умолчанию): Контейнер всегда возвращает один и тот же экземпляр (один объект в памяти). Сравнение через == будет true.
  • Бины с областью видимости prototype: При каждом запросе (getBean() или инъекции) создается новый экземпляр. Даже если эти экземпляры логически равны (equals() возвращает true), они являются разными объектами в памяти (== вернет false).
@Component
@Scope("prototype")
public class PrototypeBean {
    private String data;
    // equals() и hashCode() переопределены для сравнения по полю 'data'
}

// В коде:
PrototypeBean beanA = context.getBean(PrototypeBean.class);
PrototypeBean beanB = context.getBean(PrototypeBean.class);
beanA.setData("test");
beanB.setData("test");

System.out.println(beanA.equals(beanB)); // true (логическое равенство)
System.out.println(beanA == beanB);      // false (разные объекты в памяти)

2. В общем контексте Java:

  • == сравнивает ссылки (адреса в памяти).
  • equals() сравнивает логическое содержимое объектов (если метод переопределен).
  • Коллекции, такие как HashSet или HashMap, используют hashCode() и equals() для определения уникальности элементов. Два объекта с equals() == true будут считаться одним ключом в HashMap, даже если это разные экземпляры.

Best practice: Всегда согласованно переопределяйте equals() и hashCode() для классов, экземпляры которых будут храниться в hash-коллекциях или сравниваться по значению.