使用传递给构造函数-Java的引用是否安全
我有以下代码:使用传递给构造函数-Java的引用是否安全,java,reference,encapsulation,Java,Reference,Encapsulation,我有以下代码: 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; }
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);
}
这无疑将操纵三角形变量中引用的同一个“top”对象。
修复程序在三角形构造函数中执行以下操作:
public Triangle(Point left, Point right, Point top) {
this.left = new Point(left);
this.right = new Point(right);
this.top = new Point(top);
}
(请记住,我在Point类中有一个复制构造函数,因此上面的三条语句都是有效的)您可以在构造函数中克隆原始点,并对外部世界隐藏克隆。如果
点
已经实现了可克隆性
,或者如果您可以自己实现,请这样使用:
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());
}
这是一个很好的问题 有可变状态并不总是坏事。例如,您可以将此三角形对象实例发送到显示程序,如果您更改了点坐标,它可以在屏幕上设置三角形的动画 这取决于用例和它应该解决的问题 如果您决定,对于您的用例,整个对象图(这个对象、我的孩子和孩子的孩子等)在创建之后应该是不可变的,那么有一些方法可以确保这一点 要使不可变对象真正不可变,这里有一些很好的指导: 如果对象具有集合作为属性,则可以根据需要使用不可变或不可修改的集合: 最后,如果您确实允许可变状态,并且希望跟踪,则可以将子对象注册为观察者。 同样,原则是尽可能少地保持可变状态。换句话说,始终尽可能保持对象不变。不可变集合易于获取和使用。问题在于我们的自定义类 如果使自定义对象/模型对象完全不可变,则可能会出现复制整个对象图以更改单个属性的情况 所以,要保守。特别是对于集合,这很容易做到 在面向对象编程模式下,很难避免可变性。函数式编程应该更符合不变性。你可能想看看Haskell或Scala只是为了尝一尝
如果您有一个复制构造函数,那么使用它是安全的。否则,如果point实现,您可以使用clone。point不实现Cloneable,但我制作了一个复制构造函数,它接受一个点,并基本上基于另一个点构造一个点,这与您的第二个建议类似。是的,您完全正确,这取决于您希望应用程序如何工作。感谢您的全面回复!