链接列表插入绑定到插入的对象

时间:2010-05-06 06:53:40

标签: java linked-list immutability cloning defensive-copy

我的代码如下:

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

似乎无论什么时候我做term.add(anotherTerm)之类的事情,而另一个是另一个Term对象,看起来另一个Tim引用的东西与我刚刚插入到术语中的东西相同,所以每当我尝试更改另一个词,term.get(2)(让我们说)也改变了。

如何防止这种情况发生?

因为要求代码:

//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);
}

调用insert方法的代码:

poly.insert(anotherTerm);

创建anotherTerm术语的代码:

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

调用insert方法的新代码:

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

即使在clone() has protected access in java.lang.Object

之后,由于public class Term implements Cloneable{,仍然无效

5 个答案:

答案 0 :(得分:4)

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

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

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

Term一样简单和小的东西确实应该是不可变的。这是一个更好的整体设计,你不必担心你在问题中提出的问题。

另见


这个建议变得更加引人注目,因为其他答案暗示您使用clone()

Effective Java 2nd Edition,Item 11:明智地覆盖clone

  

由于存在许多缺点,一些专家程序员只是选择永远不会覆盖clone方法,并且永远不会调用它,除非复制数组。

来自interview with author Josh Bloch

  

如果您已经阅读了我的书中有关克隆的内容,特别是如果您在这些内容之间进行了阅读,您会发现我认为clone已经彻底破解了。

不要制作Term implements Cloneable。让它变成不可变的。

另见

答案 1 :(得分:2)

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

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

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

然后创建一个新的Term构造函数,如下所示:

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

这应该有效。

答案 2 :(得分: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)”都是对同一个对象的引用 - 改变一个会改变另一个对象。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

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

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