为什么初始值会改变而不是对象值?

时间:2014-03-19 00:44:20

标签: java object reference

这将是一个漫长的过程,因为我作为一种语言对Java来说还是比较新的。

这个程序有一个名为Point的类。这为形状的顶点创建了点。

    public class Point {

        private int x;
        private int y;

    public Point(int x, int y){

        this.x = x;
        this.y = y;

     }

在这个类中,有一些方法,如距离(2点之间),比例(按因子增加),平移(采用x和y坐标并将其添加到this.x和xy)等等。

然后我又有3个类来创建形状。三角形,矩形和圆形,构造函数看起来像这样。

    public class Triangle {

        private int sides;
        private Point[] points;

    public Triangle(Point[] vertices) {

        this.sides = 3;
        this.points = vertices;

}

    public class Rectangle {

        private int sides;
        private Point topCorner;
        private int width;
        private int length;



    public Rectangle(Point corner, int w, int l){

        this.sides = 4;
        this.topCorner = corner;
        this.width = w;
        this.length = l;

}

    public class Circle {

        private Point center;
        private int radius;

    public Circle(Point center, int radius){

        this.center = center;
        this.radius = radius;

}

所有这些类都有相同的方法翻译和缩放。这里显示了一个例子。

    //For the Rectangle Class
    public void translate(int dx, int dy){

        topCorner.translate(dx, dy);

}

我的问题出在我的班级。发生的事情是我创建了3个点,并使用全部3作为数组创建三角形,另外2个作为矩形和圆形的点。现在当我一次性调用所有3个对象的translate方法时,它最终会使值加倍,因为我相信我的错误是我已经在某处传递了对“p1”“p2”和“p3”的引用,而我更改其值而不是对象值。这是代码,我将在

之后解释输出
    public class GraphicsDemo {


 public static void main(String[] args) {
    Point p1 = new Point(0,20);
    Point p2 = new Point(20,0);
    Point p3 = new Point(30,30);


    Point[] vertices = {p1,p2,p3};

    Triangle t = new Triangle(vertices);
    Rectangle r = new Rectangle(p1,10,15);
    Circle c = new Circle (p2, 25);


    System.out.println("Triangle" + "\n" + t.toString() + "\n" + "area:" + t.area() + "\n" + "perimeter: " + t.perimeter());
    System.out.println("Reactangle" + "\n" + r.toString() + "\n" + "area:" + r.area() + "\n" + "perimeter: " + r.perimeter());
    System.out.println("Circle" + "\n" + c.toString() + "\n" + "area:" + c.area() + "\n" + "perimeter: " + c.perimeter());

    c.translate(10, 15);
    t.translate(10, 15);
    r.translate(10, 15);

System.out.println("Triangle" + "\n" + t.toString() + "\n" + "area:" + t.area() + "\n" + "perimeter: " + t.perimeter());
    System.out.println("Reactangle" + "\n" + r.toString() + "\n" + "area:" + r.area() + "\n" + "perimeter: " + r.perimeter());
    System.out.println("Circle" + "\n" + c.toString() + "\n" + "area:" + c.area() + "\n" + "perimeter: " + c.perimeter());;

这样做的输出是,如果在多个形状中使用该点,则不添加10和15到形状坐标,而是添加20和30。我确信这是因为我实际上是在更改点的值而不是对象,但我不知道如何更改它。

感谢任何可以提前帮助的人。根据我的经验,这是我第一次尝试过很多东西而且是靠墙而行。

3 个答案:

答案 0 :(得分:0)

您错过了显示代码中最重要的部分,但看起来您的分析是正确的。在您的翻译代码中,您实际上需要生成新的点实例(并替换它们)。

这通常是一个好主意,不修改对象,但保持对象不可变。确保这一点的最佳方法是跳过设置者:

class Point {
  Point(int x, int y) { this.x = x; this.y = y; }
  int getX() { return x; } intGetY() { return y; }

  /** Create a new point displaced by given coordinates. */
  Point translate(int deltaX, int deltaY) 
  {
    return new Point(this.getX() + deltaX, this.getY() + deltaY);
  }
}

答案 1 :(得分:0)

您的假设是正确的,您正在传递参考文献。圆形,三角形,矩形都与它们的构造函数中的其他形状有一个或多个共同点。请参见矩形,该矩形与三角形具有相同的点(p1)。

Point[] vertices = {p1,p2,p3};

Triangle t = new Triangle(vertices);
Rectangle r = new Rectangle(p1,10,15);
Circle c = new Circle (p2, 25);

一个简单的解决方案是克隆构造函数中的点,就像我在下面的Triangle类中所做的那样。这意味着两个形状将共享相同的x和y,但是对一个形状的更改将不再直接影响另一个形状。

类是对象引用。因此,您需要创建一个新的Object引用来创建单独的对象来处理。这就是我在点类中添加的.clone()方法,它复制了point的内部并创建了一个精确的副本。然后,其他方法的构造函数会在您提供它们的点上调用克隆方法,这样它们只会处理您为它们提供的点的副本。

class Point{

public int x;
public int y;

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

public Point clone(){

    return new Point(x,y);

}

}

class Triangle{

final static int m_sides = 3;  //constant
Point[] m_points;

Triangle(Point[] points){

    //You need to clone your ponits.
    m_points = new Point[]{
            points[0].clone(), 
            points[1].clone(),
            points[2].clone()};

}

答案 2 :(得分:0)

他们确实是同一个对象。 I.e Triangle t有p1。如果更改矩形p1,则也会更改三角形p1。

你应该在Point中做深度克隆,让它们独立。