Вставка 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
метод, но звучит так, что это проблема.