При использовании интерфейса как дженерика для List, столкнулся с тем, что изменение объекта B приводит к изменениям объекта А

Преамбула такова, хотел наполнить List 2-мя объектами с одним общим предком-интерфейсом (HasSocr)

Но, мне необходимо было сделать проверку на то, что после изменения объекты не остались равны и стали разными, дабы их можно было отдать в транзакцию на update.

private List<HasSocr> getFilledResultList(List<HasSocr> entityList) {
        List<HasSocr> resultList = new ArrayList<>();
        for (int i = 0; i < entityList.size(); i++) {
            HasSocr oldHasSocr = entityList.get(i);
            HasSocr newHasSocr = entityList.get(i);
            if (oldHasSocr != null && newHasSocr != null) {
                if (newHasSocr.getSocr() != null) {
                    newHasSocr.setSocrName(newHasSocr.getSocr().getFullName());
                    newHasSocr.setSocrShort(newHasSocr.getSocr().getScName());
                    if (!hasSocrEquals(oldHasSocr, newHasSocr)) {
                        resultList.add(entityList.get(i));
                    }
                }
            }
        }
        return resultList;
    }

private boolean hasSocrEquals(HasSocr oldHasSocr, HasSocr newHasSocr) {
        return oldHasSocr != null
                && newHasSocr != null
                && oldHasSocr.getSocrName().equals(newHasSocr.getSocrName())
                && oldHasSocr.getSocrShort().equals(newHasSocr.getSocrShort())
                && newHasSocr.getSocr().getScName().equals(oldHasSocr.getSocr().getScName())
                && newHasSocr.getSocr().getFullName().equals(oldHasSocr.getSocr().getFullName());
    }

Но обнаружил что объекты при использовании

hasSocrEquals(oldHasSocr, newHasSocr)

всегда являются одинаковыми, и больше всего меня повергло в шок то, что если пройти по строчно в дебаге, то видно что:

newHasSocr.setSocrName(newHasSocr.getSocr().getFullName());

Меняет значение поля SocrName и для объекта oldHasSocr. Отсюда и вопрос - почему?


Ответы (1 шт):

Автор решения: Nowhere Man

В коде

HasSocr oldHasSocr = entityList.get(i);
HasSocr newHasSocr = entityList.get(i);

обе ссылки oldHasSocr и newHasSocr относятся к одному и тому же i-ому элементу списка entityList, то есть к одному и тому же объекту, следовательно фактически у вас выполнится тождественное равенство oldHasSocr == newHasSocr.

Соответственно, это и есть причина того, что все изменения в объекте, на который ссылается newHasSocr отразятся и по ссылке oldHasSocr -- объект один и тот же.

Как минимум вам следовало обращаться к объектам по разным индексам типа i и i + 1, при условии что список заполнен корректно разными экземплярами.

→ Ссылка