在Java中不使用new运算符初始化一个对象

4
这两个构造函数有什么区别?
Circle (Point2D center, double radius) {
    this.center = center;
    this.radius = radius;
}

Circle (Point2D center, double radius) {
    this.center = new Point2D(center.getX(), center.getY());
    this.radius = radius;
}

以下是 Point2D 类的代码。两个版本的构造函数都能正常工作。我只是不确定它们之间有什么区别。

class Point2D {
double x;
double y;

Point2D () {
    x = 0;
    y = 0;
}

Point2D (double x, double y) {
    this.x = x;
    this.y = y;
}

void setX (double x) {
    this.x = x;
}

void setY (double y) {
    this.y = y;
}

void setXY (double x, double y) {
    this.x = x;
    this.y = y;
}

double getX () {
    return x;
}

double getY () {
    return y;
}

double distance (Point2D p) {
    double x1 = p.getX();
    double y1 = p.getY();
    return Math.sqrt(Math.pow(x1 - x, 2) + Math.pow(y1 - y, 2));
}

double distance (double x, double y) {
    return Math.sqrt(Math.pow(x - this.x, 2) + Math.pow(y - this.y, 2));
}

Circle类有2个字段,中心点和半径。中心点是Point2D类型,半径是double类型。我尝试编译和运行了构造函数的两个版本,两个版本都可以正常工作。所以我很困惑应该使用哪个版本,以及它们之间的区别,因为在第一个版本中我没有使用new操作来初始化中心点对象。

4个回答

4

第二个构造函数使用原始center实例的defensive copy(由Point2D构造函数调用生成),以防止进一步的突变(更改)输入实例,这可能会非常混乱并产生错误。

所以我不确定哪个更好并且为什么

第二种方法更安全,因为您的Point2D类是可变的。它使用更多内存(以容纳额外的防御性副本),但在真正复杂的项目中,这种设计实践的优点比缺点更多。

如果您可以使Point2Dimmutable,那么使用第一个构造函数就可以了。


3
第二个构造函数创建了一个新的Point实例 - this.center = new Point2D(center.getX(), center.getY());,而不是保留对它传递进来的实例的引用。这意味着如果传递的center后来被修改,那么这些变化不会影响Circle实例。
第二个构造函数通常更安全,因为它具有真正私有的Point实例作为Circle的中心,而第一个构造函数与调用者共享center
您可以通过以下代码看到区别:
Point2D point = new Point2D(10.0, 20.0);
Circle circle = new Circle (point, 4.0);
point.setX (5.0);
System.out.println(circle); // assuming you override toString to display the properties
                            // of the Circle

如果您使用第一个构造函数,执行此代码后,您的圆将具有中心点(5.0,20.0),而如果您使用第二个构造函数,则圆将具有中心点(10.0,20.0)。

所以,就像第一个构造函数没有使用任何内存空间一样,它只使用了存储我传递的中心对象地址的空间。 - Xtr33mm
在使用第一个构造函数后,this.centercenter 变量将持有同一个共享的 Point2D 实例的引用。而在第二个构造函数调用后,会创建一个额外的实例(防御性拷贝)- this.centercenter 将使用独立的引用(Point2D 值)。 - Cootri
@Xtr33mm 构造函数不占用空间。您的 Circle 类的实例变量使用空间。它们使用空间来存储对 Point2D 实例和 double 的引用。第二个构造函数创建了一个额外的 Point2D 对象,因此可以说运行使用第二个构造函数的程序将需要更多的空间。 - Eran

0

Point2D 不是不可变的,即在构建点之后可以更改其属性。

Circle 的第一个构造函数仅使用 Point2D 对象 - 现在调用者可以更改点对象,这也会影响圆形。

Circle 的第二个构造函数创建了 Point2D 对象的一个副本。如果圆形将点对象保持为私有,则无法从外部更改它。


0

this.center = center,你使用了center对象的参数。

this.center = new Point2D(center.getX(), center.getY()),你创建了一个Point2D对象,并使用了center值作为参数。


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