即使我已经将Face类声明为final类,它似乎也不是一成不变的,该如何纠正呢?

时间:2019-03-15 04:16:16

标签: java immutability transpose

我正在尝试使Face类不可变,以使Face对象一旦初始化就不会更改。这是我到目前为止的内容:

public class Face{
  protected final int[][] grid;
  protected Face half;

  public Face(int[][] grid){
    this.grid = grid;
  }


  public Face rotateRight(){
    int rows = 3;
    int cols = 3;
    int[][] transposedArray = new int[3][3];

    for (int i = 0; i<rows; i++){
      for (int j = 0; j<cols; j++){
        transposedArray[i][j]=grid[rows-j-1][i];
      }
    }

    return new Face(transposedArray);
  }

  public Face rotateLeft(){
    int rows = 3;
    int cols = 3;
    int[][] transposedArray = new int[3][3];

    for (int i = 0; i < 3; i++){
      for (int j = 0; j < 3; j++){
        transposedArray[2-j][i] = grid[i][j];
      }
    }
    return new Face(transposedArray);
  }

  public Face rotateHalf(){
    half = this.rotateRight();
    half = half.rotateRight();
    return half;
  }

  public int[][] getGrid(){
    return (this.grid).clone();
    }

  public String toString(){
    String str = "";
    for (int i = 0; i<3;i++){
      for (int j = 0; j<3; j++){
        str += String.format("%02d",grid[i][j]);
      }
    }
    String str1 = str.substring(0,6);
    String str2 = str.substring(6,12);
    String str3 = str.substring(12,18);
    return str1+"\n"+str2+"\n"+str3;
  }
}

但是,当我尝试运行以下命令时:

int[][] g = f.getGrid();
g[1][1] = 9;

我希望f保持为

010203
040507
070809

但我最终得到了

010203
040906
070809

相反。即使我已经将该类声明为final,我的Face对象也不会保持不变吗?

3 个答案:

答案 0 :(得分:1)

您需要在构造函数中制作输入grid的防御性副本。

另外,尽管我怀疑最后两点不是造成您问题的原因,但字段也应为private,类也应为{​​{1}}。

未测试:

final

答案 1 :(得分:0)

您的问题可能是您的构造函数未克隆传入的数组。因此,也许创建Face类实例的代码稍后会操纵它传递给新Face对象的数组!

不幸的是,没有办法在Java中创建真正的不可变数组。将数组声明为final只会阻止您整体更改数组,仍然可以更改该数组中的各个行,列,插槽。

如果您想要不可变的集合,则需要打开实际的Collection类,然后使用Collections类中的方法在它们之上创建不可修改的视图。

答案 2 :(得分:0)

使用clone时要小心。

在数组上,它会进行浅表复制。以下代码片段对其进行了更好的解释:

int[] c0 = new int[]{1, 2, 3};
int[] c1 = new int[]{4, 5, 6};
int[] c2 = new int[]{7, 8, 9};
int[][] grid = new int[][]{c0, c1, c2};
int[][] cloned = grid.clone();

assert cloned[0] == c0;
assert cloned[1] == c1;
assert cloned[2] == c2;