1

我的代码如下所示:

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

并且似乎每当我做类似 的事情时term.add(anotherTerm), anotherTerm 是......另一个 Term 对象,似乎 anotherTerm 引用的内容与我刚刚插入 term 的内容相同,因此每当我尝试更改 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);

创建 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{

4

5 回答 5

4

解决方案很简单:使Term不可变。

Effective Java 第 2 版,第 15 项:最小化可变性

  • 不可变对象很简单。
  • 不可变对象可以自由共享。
  • 不可变对象为其他对象提供了很好的构建块。
  • 类应该是不可变的,除非有充分的理由使它们可变。
  • 如果一个类不能成为不可变的,则尽可能限制它的可变性。
    • final除非有令人信服的理由将其设为非final

Term真正应该使简单而小的东西不可变。这是一个更好的整体设计,您不必担心您在问题中提出的问题。

也可以看看


由于其他答案建议您使用clone().

Effective Java 第 2 版,第 11 项:clone明智地覆盖

由于存在许多缺点,一些专业程序员只是选择从不覆盖该clone方法并且从不调用它,除非可能是为了复制数组。

来自对作者 Josh Bloch 的采访

如果你读过我书中关于克隆的项目,尤其是如果你读到字里行间,你就会知道我认为clone它被深深地破坏了。

不要Term implements Cloneable。改为不可变。

也可以看看

于 2010-05-06T07:09:11.160 回答
2

好的,用这个替换我的旧答案,现在我更好地理解了这个问题和行为。

如果你愿意,你可以这样做:

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

然后像这样创建一个新的 Term 构造函数:

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

那应该行得通。

于 2010-05-06T07:07:28.993 回答
2

编辑:好的,我想我知道你现在在做什么。如果你有这个课程:

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)”都是对同一个对象的引用——改变一个对象会改变另一个对象。

于 2010-05-06T07:15:15.623 回答
1

问题不太清楚,但我只是尝试,当您添加对象时,添加 anotherTerm.clone()

于 2010-05-06T07:01:02.017 回答
1

听起来你没有实例化 new Object,只是引用同一个。Term您应该使用Term term = new Term();或通过克隆实例化一个 new term.clone()

EDIT 能够被克隆,Term需要实现Cloneable接口。这意味着您负责如何Term定义 a 的新副本。

如果没有看到调用该insert方法的代码就很难说,但听起来这就是问题所在。

于 2010-05-06T07:02:33.183 回答