Java中对象的双重引用

4

有一个类:

public class Rectangle {
    public int width = 0;
    public int height = 0;
    public Point origin;

    public Rectangle(Point p) {
        origin = p;
    }
}

如您所见,该类具有类型为Point的对象。当我声明类型为Rectangle的对象时,

Rectangle rectOne = new Rectangle(originOne)

如果originOne是Point类型,那么在对象初始化后,我将有两个不同的引用指向由originOne引用的Point,即rectOne.origin和originOne。 如果为了使代码更安全而想要摆脱其中一个变量,除了编写构造函数以避免创建额外对象之外,是否还有其他方法可以做到这一点?


1
最好使用 new Rectangle ( new Point ( x, y ) );这样你只有一个对原点的引用。(提示:使用 getter 方法访问 origin,如 public getOrigint() { return origin; })。 - Hungry Blue Dev
2个回答

4
如果我想为了让代码更安全而摆脱其中一个变量怎么办? 你的提问方式有些奇怪。我猜你想确保别人不能通过后续更改originOne来影响rectOne。 除了编写构造函数以避免创建额外对象之外,还有其他方法吗? 你的解决方案就在你的问题中:创建一个额外的对象。
public Rectangle(Point p) {
    origin = new Point(p.x, p.y);
}

或者

public Rectangle(Point p) {
    origin = p.clone();
}

它将需要支持clone方法,以支持最后一个。请参阅此链接或其他引用了解其涉及的内容。
如果您想这样做而不创建另一个对象,(1)您可能无法这样做,(2)为什么要限制自己不创建对象呢?这就是面向对象编程的精髓。
对于String,您通常不会有同样的担忧。为什么?因为它们是不可变的。
另一个(在我看来更好的)解决方案是使Point类是不可变的。
public class Point { // possibly add "final class" 
    final int x;
    final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

现在没有人可以改变一个Point,你的代码变得“更安全”了。


但是,再次使用clone()会返回引用的副本。如果其中一个被更改,两个引用都会更新吗? - Hungry Blue Dev
3
@ambigram_maker,不是返回指向旧对象的引用,而是返回一个指向新对象的引用,这个新对象(理论上)"等同于"旧对象。但它在内存中是一个不同的对象。改变其中一个对象不会改变另一个对象。 - Paul Draper
好的...但是ArrayList上的clone()方法会返回一个新的ArrayList,其中包含对象的引用,对吗?(这就是我感到困惑的地方) - Hungry Blue Dev
2
@ambigram_maker,是的。它返回一个新的 ArrayList。你说得对,它将具有与旧ArrayList相同的元素引用。如果你想要一个新的ArrayList,并且还要新的元素,那么你必须进行深度复制;clone只做浅层复制。但很可能你的Point类已经引用了原始类型,所以在这种情况下这可能并不重要。 - Paul Draper
因此,原始数据类型不需要更新,只有“对象”需要更新。(感谢@Paul) :-) - Hungry Blue Dev
1
@ambigram_maker,为了明确起见,原始类型(或其包装类,例如Integer)在这方面并不是真正的特殊例外。对于任何不可变类,如IntegerString等,都是如此。您自己的类也可以具有相同的“行为”(至少在这方面是这样)。 - Paul Draper

2
当您像您所做的那样编写代码时,没有创建Point类的额外对象,您只是在一个新变量中创建对存储在同一对象中的相同对象的新引用。
如果您想确保不会创建到同一Point对象的其他引用,请将点的X和Y传递给Rectangle类,并在构造函数中创建一个新对象。
public Rectangle(int x, int y) {
    origin = new Point(x, y);
}

这样做可以很清楚地表明您没有存储传递参数的引用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接