这是一个不可改变的类吗?

Den*_* S. 12 java arrays immutability

我不知道不可变类应该是什么样子但是我很确定这个是.我对吗?如果我不是请指定应添加/删除的内容.

import java.io.Serializable;

public class Triangle implements IShape, Serializable {
    private static final long serialVersionUID = 0x100;

    private Point[] points;

    public Triangle(Point a, Point b, Point c) {
        this.points = new Point[]{a, b, c};
    }

    @Override
    public Point[] getPoints() {
        return this.points;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) return false;
        if (this == obj) return true;
        if (getClass() != obj.getClass()) return false;
        Point[] trianglePoints = ((Triangle) obj).getPoints();
        for (int i = 0; i < points.length; i++){
            if (!points[i].equals(trianglePoints[i])) return false;
        }
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

这会诀窍吗?

@Override
    public Point[] getPoints() {
        Point[] copyPoint = {
                new Point(points[0]),
                new Point(points[1]),
                new Point(points[2]),};
        return copyPoint;
    }
Run Code Online (Sandbox Code Playgroud)

点类:

import java.io.Serializable;

public class Point implements Serializable {
    private static final long serialVersionUID = 0x100;

    public int x;
    public int y;
    public int z;

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

    public Point(Point that) {
        this.x = that.x;
        this.y = that.y;
        this.z = that.z;
    }

    public boolean equals(Object obj) { 
        // assume this is a typical, safe .equals implementation
        // that compares the coordinates in this instance to the
        // other instance
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*hes 17

不,您可以更改Points数组中的内容.如果你想让它一成不变的,有吸手出的点阵列的副本,而不是原件.

试试这个:

Triangle triangle = new Triangle(a, b, c);
triangle.getPoints()[1] = null;
System.out.println(Arrays.toString(triangle.getPoints()));
Run Code Online (Sandbox Code Playgroud)

另外一点需要不变(如尼基塔Rybak的指出).有关如何复制数组,请参阅如何使用Java复制数组.

  • 此外,_Point_类应该是不可变的.做_triangle.getPoints()[0] .setX(3)_也会制造不变性. (6认同)

dty*_*dty 10

不,这不对.您公开Point []并且调用者可以修改其内容.另外,你的类不是最终的,所以有人可能会通过继承它颠覆它.

  • 但是如果Point不是不可变的,那么孩子可以调用`super(pointA,pointB,pointC)`,保持对点的本地引用并改变它们.现在谁在虐待谁?:-) (3认同)
  • 他们不能通过子类化来破坏它.唯一的数据"点"是私人的.子类无法查看其父级的私有数据.(这将是乱伦或虐待儿童或其他什么.) (2认同)
  • 我不知道你在看哪个String,但我最看的那个绝对是最终的. (2认同)

Ron*_*onU 8

不,这绝对是可变的.

你不仅暴露了实际的Point []数组,而且在通过构造函数获取它们时,你没有防御复制(Bloch第2版,第39项)Point对象本身.

  1. Point []数组可以删除或添加项目,因此它是可变的.
  2. 您可以传入点a,b和c,然后在它们上调用setX()或setY()以在构造后更改其数据.

  • #2的+1,没有被其他人直接解决. (3认同)

Sea*_*oyd 6

关.首先,一个不可变的类应该使它的字段最终,但这不是一个要求.

但是,您通过getter公开数组,这不是不可变的.使用Arrays.copyOf(数组,长度)制作防御性副本:

@Override
public Point[] getPoints() {
    return Arrays.copyOf(this.points,this.points.length);
}
Run Code Online (Sandbox Code Playgroud)

  • 给出实施的+1 ......因为我厌恶它,当我被你的答案打得像你一样.:) (2认同)