Вставка LinkedList привязана к вставленному объекту

У меня есть код, который выглядит так:

public class Polynomial {
    List<Term> term = new LinkedList<Term>();

и кажется, что всякий раз, когда я делаю что-то вроде term.add(anotherTerm)с другими объектами Term, являющимися... другим объектом Term, кажется, что otherTerm ссылается на то же самое, что и то, что я только что вставил в термин, так что всякий раз, когда я пытаюсь изменить другой объект Term, term.get(2) (скажем) get тоже изменяется,

Как я могу предотвратить это?

Так как код был запрошен:

//since I was lazy and didn't want to go through the extra step of Polynomial.term.add
public void insert(Term inserting) {
    term.add(inserting);
}

Код, вызывающий метод вставки:

poly.insert(anotherTerm);

Код, создающий другой срок:

Term anotherTerm = new Term(3, 7.6); //sets coefficient and power to 3 and 7.6

Новый код, вызывающий метод вставки:

poly.insert((Term)anotherTerm.clone());

К сожалению, до сих пор не работает из-за clone() has protected access in java.lang.Objectдаже после выполнения public class Term implements Cloneable{

5 ответов

Решение

ОК, заменив мой старый ответ этим, теперь, когда я лучше понимаю вопрос и поведение.

Вы можете сделать это, если вам нравится:

public void insertTerm(Term term) {
    polynomial.insert(new Term(term));
}

а затем создайте новый конструктор Term следующим образом:

public Term(Term term) {
    this.coefficient = term.coefficient;
    this.exponent = term.exponent;
}

Это должно работать.

Решение простое: сделать Term неизменный.

Эффективное Java, 2-е издание, пункт 15: минимизируйте изменчивость:

  • Неизменные объекты просты.
  • Неизменяемые объекты могут быть переданы свободно.
  • Неизменяемые объекты создают отличные строительные блоки для других объектов.
  • Классы должны быть неизменяемыми, если только нет веской причины сделать их изменяемыми.
  • Если класс нельзя сделать неизменным, максимально ограничьте его изменяемость.
    • Сделайте каждое поле final если нет веских причин сделать это final

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

Смотрите также


Этот совет становится еще более убедительным, так как другие ответы предполагают, что вы используете clone(),

Эффективное Java, 2-е издание, пункт 11: переопределение clone рассудительно

Из-за многих недостатков некоторые опытные программисты просто предпочитают никогда не переопределять clone метод и никогда не вызывать его, кроме, возможно, для копирования массивов.

Из интервью с автором Джош Блох:

Если вы читали статью о клонировании в моей книге, особенно если вы читаете между строк, вы знаете, что я думаю, clone глубоко сломан.

НЕ делай Term implements Cloneable, Сделайте это неизменным вместо этого.

Смотрите также

РЕДАКТИРОВАТЬ: Хорошо, я думаю, что я вижу, что вы делаете сейчас. Если у вас есть этот класс:

public class Polynomial 
{
    List<Term> term = new LinkedList<Term>();

    public void insert(Term inserting) 
    {
       term.add(inserting);
    }
}

И тогда вы делаете это:

Polynomal poly = new Polynomal()
Term term = new Term();
poly.insert(term);
term.coefficient = 4;

... тогда термин объекта - это тот же объект, что и poly.get(0). "term" и "poly.get(0)" являются ссылками на один и тот же объект - изменение одного изменит другой.

Вопрос не так понятен, но я просто пытаюсь, когда вы добавляете объекты, добавьте anotherTerm.clone()

Звучит так, будто вы не создаете новый экземпляр Objectс, просто ссылаясь на тот же. Вы должны создать новую Termлибо с Term term = new Term(); или путем клонирования term.clone(),

РЕДАКТИРОВАТЬ, чтобы иметь возможность клонировать, Term необходимо реализовать интерфейс Cloneable. Это означает, что вы несете ответственность за то, как новая копия Term должны быть определены.

Трудно сказать, не видя код, который вызывает insert метод, но звучит так, что это проблема.

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