我无法在Java中创建一个不可变的类。我知道我的构造函数可能会遇到一些问题,也可能是我的getter方法。从我所读到的,听起来我需要制作不引用原始对象的新对象。
如果可能的话,我想要一些帮助,引导我如何使这个类不可变。
public class FMatrix implements Matrix {
private final int rows, columns;
private final int[][] matrix;
//TODO: implement interface.
public FMatrix(int[][] matrix) {
int[][] matrix1;
if (matrix.length == 0) {
rows = 0;
columns = 0;
} else {
rows = matrix.length;
columns = matrix[0].length;
}
this.matrix = new int[rows][columns];
//this.matrix = matrix;
}
/**
* Returns the element at particular point in the matrix.
* @param y y position
* @param x x position
* @return element
*/
@Override
public int getElement(int y, int x) {
return matrix[y][x];
}
/**
* Returns the number of rows in the matrix.
* @return rows
*/
@Override
public int getRows() {
return rows;
}
/**
* Returns the number of columns in the matrix.
* @return columns
*/
@Override
public int getColumns() {
return columns;
}
/**
* Returns this matrix scaled by a factor. That is, computes kA where k is a
* constant and A is a matrix (this object).
*
* @param scalar scalar
* @return matrix
*/
@Override
public Matrix scale(int scalar) {
int value;
int[][] mat1;
int newRows = getRows();
int newColumns = getColumns();
mat1 = new int[newRows][newColumns];
//this.matrix = new int[newRows][newColumns];
FMatrix newMatrix = new FMatrix(mat1);
for (int i = 0; i < getRows(); i++) {
for (int j = 0; j < getColumns(); j++) {
value = getElement(i, j) * scalar;
mat1[i][j] = value;
}
}
return newMatrix;
}
/**
* Returns this matrix added with another matrix. That is, computes A+B where
* A and B are matrices (this object, and another respectively).
* @param other addend
* @return matrix
* @throws RuntimeException if matrices do not have matching dimensions.
*/
@Override
public Matrix plus(Matrix other) {
int value;
int newRows = getRows();
int newColumns = getColumns();
if (newRows != other.getRows() || newColumns != other.getColumns()) {
throw new RuntimeException();
}
FMatrix newMatrix = new FMatrix(matrix);
for (int i = 0; i < newRows; i++) {
for (int j = 0; j < newColumns; j++) {
value = getElement(i, j) + other.getElement(i, j);
this.matrix[i][j] = value;
}
}
return newMatrix;
}
/**
* Returns this matrix subtracted by another matrix. That is, computes A-B
* where A and B are matrices (this object, and another respectively).
* @param other subtrahend
* @return matrix
* @throws RuntimeException if matrices do not have matching dimensions.
*/
@Override
public Matrix minus(Matrix other) {
int value;
int newRows = getRows();
int newColumns = getColumns();
//throw exception if dimensions do not match
if (newRows != other.getRows() || newColumns != other.getColumns()) {
throw new RuntimeException("Dimensions do not match");
}
FMatrix newMatrix = new FMatrix(matrix);
for (int i = 0; i < newRows; i++) {
for (int j = 0; j < newColumns; j++) {
value = getElement(i, j) - other.getElement(i, j);
this.matrix[i][j] = value;
}
}
return newMatrix;
}
/**
* Returns true if this matrix matches another matrix.
* @param other another matrix
* @return equality
*/
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else {
return false;
}
}
/**
* Returns a string representation of this matrix. A new line character will
* separate each row, while a space will separate each column.
* @return string representation
*/
@Override
public String toString() {
String str = "";
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
str += getElement(i, j) + " ";
if (j == columns - 1) {
str += "\n"; //add a new line for next row
}
}
}
return str;
}
主要方法
public static void main(String [] args){
int[][] data1 = new int[0][0];
int[][] data2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int[][] data3 = {{1, 4, 7}, {2, 5, 8}, {3, 6, 9}};
Matrix m1 = new FMatrix(data1);
Matrix m2 = new FMatrix(data2);
Matrix m3 = new FMatrix(data3);
System.out.println("m1 --> Rows: " + m1.getRows() + " Columns: " + m1.getColumns());
System.out.println("m2 --> Rows: " + m2.getRows() + " Columns: " + m2.getColumns());
System.out.println("m3 --> Rows: " + m3.getRows() + " Columns: " + m3.getColumns());
//check for reference issues
System.out.println("m2 -->\n" + m2);
data2[1][1] = 101;
System.out.println("m2 -->\n" + m2);
//test equals
System.out.println("m2==null: " + m2.equals(null)); //false
System.out.println("m3==\"MATRIX\": " + m2.equals("MATRIX")); //false
System.out.println("m2==m1: " + m2.equals(m1)); //false
System.out.println("m2==m2: " + m2.equals(m2)); //true
System.out.println("m2==m3: " + m2.equals(m3)); //false
//test operations (valid)
System.out.println("2 * m2:\n" + m2.scale(2));
System.out.println("m2 + m3:\n" + m2.plus(m3));
System.out.println("m2 - m3:\n" + m2.minus(m3));
//test operations (invalid)
//System.out.println("m1 + m2" + m1.plus(m2));
//System.out.println("m1 - m2" + m1.minus(m2));
}
这是main中测试的输出。问题是在调用.scale()方法后不应更改m2对象。
m1 --> Rows: 0 Columns: 0
m2 --> Rows: 3 Columns: 3
m3 --> Rows: 3 Columns: 3
m2 -->
1 2 3
4 5 6
7 8 9
m2 -->
1 2 3
4 101 6
7 8 9
m2==null: false
m3=="MATRIX": false
m2==m1: false
m2==m2: true
m2==m3: false
2 * m2:
2 4 6
8 202 12
14 16 18
m2 + m3:
2 6 10
6 106 14
10 14 18
m2 - m3:
1 2 3
4 101 6
7 8 9
答案 0 :(得分:0)
您的操作方法似乎有错误。考虑scale
FMatrix newMatrix = new FMatrix(mat1);
for (int i = 0; i < getRows(); i++) {
for (int j = 0; j < getColumns(); j++) {
value = getElement(i, j) * scalar;
mat1[i][j] = value;
}
}
return newMatrix;
这很棒,因为您[i][j]
的作业已在mat1
上。但看看你在plus
!!
FMatrix newMatrix = new FMatrix(matrix);
for (int i = 0; i < newRows; i++) {
for (int j = 0; j < newColumns; j++) {
value = getElement(i, j) + other.getElement(i, j);
this.matrix[i][j] = value;
}
}
return newMatrix;
哦,亲爱的,你正在改变this.matrix[i][j]
- 你的班级不再是不可改变的。但更重要的是,你返回的价值也被破坏了。所以我相信你只需修复这个bug,你的类实际上就是不可变的。
其他错误:
副本是必要的,所以你不能这样做
int[][] matrix = new int[3][3];
FMatrix f = new FMatrix(matrix);
matrix[1][1] = 42; // broken immutability
现在它不是问题,因为你从不将参数中的值分配给矩阵......所以不用担心。
public FMatrix(int[][] matrix) {
if (matrix.length == 0) {
rows = 0;
columns = 0;
} else {
rows = matrix.length;
columns = matrix[0].length;
}
this.matrix = new int[rows][0];
for(int row = 0; row < rows; row++) {
this.matrix[rows] = matrix[rows].clone();
}
}