使用传递给构造函数的引用是否可以安全 - Java

Is it ok and safe to work with references passed to constructor - Java

我有以下代码:

public class Triangle {

    private Point left;
    private Point right;
    private Point top;

    public Triangle(Point left, Point right, Point top) {
        this.left = left;
        this.right = right;
        this.top = top;
    }

    // more program logic...
}

我想知道这样构造一个对象是否可以安全,因为我担心类型为 Point 的三个变量中的某些变量可以从外部修改(破坏封装)。 例如:

public static void main(String[] args) {

    Point left = new Point(0.0, 1.0);
    Point right = new Point(2.4, 3.2);
    Point top = new Point(5.8, 2.0);

    Triangle t = new Triangle(left, right, top);

    top.setX(10.2);
    top.setY(23.4); 
}

这无疑将操纵在 Triangle 变量中引用的同一个 "top" 对象。 在 Triangle 构造函数中执行以下操作也是如此:

public Triangle(Point left, Point right, Point top) {
    this.left = new Point(left);
    this.right = new Point(right);
    this.top = new Point(top);
}

(记住我在点class中有一个复制构造函数,所以上面的三个语句是有效的)

您可以在构造函数中克隆原始点,并使克隆对外界隐藏。如果 Point 已经实现了 Cloneable 或者如果你可以自己实现它,那么使用它:

public Triangle(Point left, Point right, Point top) {
    this.left = left.clone();
    this.right = right.clone();
    this.top = top.clone();
}

如果 Point 没有实现 Cloneable 并且您无法访问其源代码,只需手动克隆点:

public Triangle(Point left, Point right, Point top) {
    this.left = new Point(left.getX(), left.getY());
    this.right = new Point(right.getX(), right.getY());
    this.top = new Point(top.getX(), top.getY());
}

这是个很好的问题。

具有可变状态并不总是坏事。例如,您可以将此三角形 object 实例发送到显示程序,如果您更改点 co-ordinates,它可以在屏幕上为三角形设置动画。

这取决于用例和它应该解决的问题。

如果您下定决心,对于您的用例,整个 object 图(这个 object、我的 children 和 children 的 children等)一旦创建就应该是不可变的,有一些方法可以确保这一点。

为了使不可变 object 真正不可变,这里有一些很好的指导: http://www.javapractices.com/topic/TopicAction.do?Id=29

如果 object 将集合作为属性,您可以根据需要使用 Immutable 或 Unmodifiable 集合: Java Immutable Collections

最后,如果您确实允许可变状态,并希望保持跟踪,您可以在 child object 中注册为观察者。 When should we use Observer and Observable

同样,原则是尽可能少地保留可变状态。换句话说,总是尽可能保持 objects 不可变。不可变集合很容易获得且易于使用。问题出在我们的习惯 类 上。

如果您使自定义 object/model object 完全不可变,您可能会遇到复制整个 object 图表以更改单个 属性 的情况。

所以,要保守一点。尤其是集合,很容易做到。

使用Object 面向编程范式很难避免可变性。函数式编程应该更符合不变性。您可能想看看 Haskell 或 Scala 来尝尝鲜。

https://softwareengineering.stackexchange.com/questions/232711/complete-immutability-and-object-oriented-programming

如果您有复制构造函数,那么您可以放心使用它。否则,您可以使用 clone if point implements cloneable.