Вставка LinkedList привязана к вставленному объекту - PullRequest
1 голос
/ 06 мая 2010

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

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

и кажется, что всякий раз, когда я делаю что-то вроде term.add(anotherTerm), когда anotherTerm является ... другим объектом Term, кажется, что anotherTerm ссылается на то же самое, что я только что вставил в термин, так что всякий раз, когда я пытаюсь изменить anotherTerm, 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 ]

4 голосов
/ 06 мая 2010

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

Effective Java 2nd Edition, Item 15: Минимизируйте изменчивость :

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

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

Смотри также


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

Effective Java 2nd Edition, Item 11: Override clone, разумно

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

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

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

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

Смотри также

* * 1068 Как правильно переопределить метод клонирования? Почему люди так боятся использовать clone () (на уроках коллекции и JDK)?
2 голосов
/ 06 мая 2010

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

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)» являются ссылками на один и тот же объект - изменение одного изменит другой.

2 голосов
/ 06 мая 2010

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

Вы можете сделать это, если хотите:

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

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

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

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

1 голос
/ 06 мая 2010

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

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

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

1 голос
/ 06 мая 2010

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

...