Мой класс Face, кажется, не является неизменным, хотя я уже объявил его как окончательный, как мне исправить это? - PullRequest
0 голосов
/ 15 марта 2019

Я пытаюсь сделать свой класс 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

вместо этого. Разве мой объект Face не сделан неизменным, хотя я уже объявил класс как final?

Ответы [ 3 ]

1 голос
/ 15 марта 2019

Вам нужно сделать защитную копию ввода grid в конструкторе.

Кроме того, поля также должны быть private, а класс тоже должен быть final, хотя яподозреваю, что последние два пункта не являются причиной вашей проблемы.

Не проверено:

  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;
  }
0 голосов
/ 15 марта 2019

Будьте осторожны при использовании 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;
0 голосов
/ 15 марта 2019

Ваша проблема может заключаться в том, что ваш конструктор не клонирует входящий массив. Поэтому, возможно, код, который создает экземпляр класса Face, позже манипулирует массивом, который он передал новому объекту Face!

К сожалению, в Java нет способа создать действительно неизменяемые массивы. Объявление массива как окончательного только препятствует тому, чтобы вы изменили массив в целом, все еще возможно изменить отдельные строки, столбцы, слоты в этом массиве.

Если вы хотите неизменные коллекции, вам нужно повернуть фактические классы Collection и затем использовать методы в классе Collections для создания неизменяемых представлений над ними.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...