使用传递给构造函数的引用是否可以安全 - 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 来尝尝鲜。
如果您有复制构造函数,那么您可以放心使用它。否则,您可以使用 clone if point implements cloneable.
我有以下代码:
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 来尝尝鲜。
如果您有复制构造函数,那么您可以放心使用它。否则,您可以使用 clone if point implements cloneable.