我的脸 class 似乎不是一成不变的,即使我已经声明它是最终的,我该如何纠正它?
My Face class does not seem to be immutable even though I already declared it as final, how do I correct it?
我试图让我的脸 class 不可变,这样我的脸对象在初始化后就不会改变。这是我目前所拥有的:
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
相反。即使我已经将 class 声明为最终的,我的 Face 对象是否没有变得不可变?
您需要在构造函数中制作输入的防御副本 grid
。
另外,字段也应该是 private
,class 也应该是 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;
}
您的问题可能是您的构造函数没有克隆传入数组。所以也许创建 Face class 实例的代码稍后会操纵它传递给新 Face 对象的数组!
不幸的是,在 Java 中无法创建真正不可变的数组。将数组声明为 final 只会阻止您更改整个数组,仍然可以更改该数组中的个别行、列、槽。
如果您想要不可变的集合,您需要转换实际的集合 classes,然后使用集合中的方法 class 在它们之上创建不可修改的视图。
使用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;
我试图让我的脸 class 不可变,这样我的脸对象在初始化后就不会改变。这是我目前所拥有的:
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
相反。即使我已经将 class 声明为最终的,我的 Face 对象是否没有变得不可变?
您需要在构造函数中制作输入的防御副本 grid
。
另外,字段也应该是 private
,class 也应该是 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;
}
您的问题可能是您的构造函数没有克隆传入数组。所以也许创建 Face class 实例的代码稍后会操纵它传递给新 Face 对象的数组!
不幸的是,在 Java 中无法创建真正不可变的数组。将数组声明为 final 只会阻止您更改整个数组,仍然可以更改该数组中的个别行、列、槽。
如果您想要不可变的集合,您需要转换实际的集合 classes,然后使用集合中的方法 class 在它们之上创建不可修改的视图。
使用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;