简体   繁体   English

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

[英]My Face class does not seem to be immutable even though I already declared it as final, how do I correct it?

I am trying to make my Face class immutable such that my Face object will not change once it has been initialized. 我正在尝试使我的Face类不可变,以使Face对象一旦初始化就不会更改。 This is what I have so far: 这是我到目前为止的内容:

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;
  }
}

However, when I try to run the following: 但是,当我尝试运行以下命令时:

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

I expect f to remain as 我希望f保持为

010203
040507
070809

but I end up getting 但我最终得到

010203
040906
070809

instead. 代替。 Is my Face object not made immutable even though I have already declared the class as final? 即使我已经将该类声明为final,我的Face对象也不会保持不变吗?

You need to make a defensive copy of the input grid in the constructor. 您需要在构造函数中创建输grid的防御性副本。

Also, the fields should be private as well, and the class should be final too, although I suspect those last two points are not the cause of your problem. 同样,这些字段也应该是private ,并且该类也应该是final ,尽管我怀疑最后两点不是造成问题的原因。

Not tested: 未经测试:

  public Face(int[][] grid){
    int temp[][] = new int[ grid.length ][];
    for( int i = 0; i < temp.length; i++ ) 
      temp[i] = Arrays.copyOf( grid[i], grid[i].length );
    this.grid = temp;
  }

Your problem could be that your constructor doesn't clone the incoming array. 您的问题可能是您的构造函数没有克隆传入的数组。 So maybe the code that creates the Face class instance later manipulates the array it passed to the new Face object! 因此,也许创建Face类实例的代码稍后会操纵它传递给新Face对象的数组!

Unfortunately, there is no way to create truly immutable arrays in the Java. 不幸的是,没有办法在Java中创建真正的不可变数组。 Declaring an array as final only prevents you from changing the array as a whole, it is still possible to change individual rows, columns, slots in that array. 将数组声明为final只会阻止您整体更改数组,仍然可以更改该数组中的各个行,列,插槽。

If you want immutable collections, you need to turn actual Collection classes and then use the methods within the Collections class to create unmodifiable views over them. 如果要使用不可变的集合,则需要打开实际的Collection类,然后使用Collections类中的方法在其上创建不可修改的视图。

Be careful when using clone . 使用clone时要小心。

On arrays, it does a shallow copy. 在阵列上,它会进行浅表复制。 The following snippet explains it better: 以下代码片段对其进行了更好的解释:

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Java 变量不在 scope 中,即使我已经在 class 中声明了它? - Java variable is out of scope even though I've already declared it in the class? 为什么即使我声明了 rand,它也会给我一个错误? - Why does it give me an error even though I declared rand? 我是否需要防御性的复制,以* non final *构建一个不可变的类,尽管它是不可变的字段? - Do I need defensive copying constructing an immutable class with *non final* albeit immutable fields? 当我已经声明了类时,为什么需要=(class)…? - why do I need = (class) … when I already declared the class? 获取FileNotFoundException,即使我声明它被抛出 - Getting FileNotFoundException even though I declared it to be thrown 边界更新,即使已声明为最终边界 - Bounds updating even though declared as final 如何确定我的班级是一成不变的 - How can I be sure that my class is immutable 为什么即使凭据正确,我也会收到 401 unauthorized? - Why do i get 401 unauthorised even though credentials are correct? 为什么String类是不可变的,即使它有一个名为“hash”的非最终字段 - Why String class is immutable even though it has a non -final field called “hash” 为什么即使在匿名函数中更改了声明为final的对象的状态,似乎也要重置? - Why does the state of an object declared as final seem to be reset even when it's altered inside an anonymous function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM