尽管限制了访问,Java类变量并不是不可变的



我已经编写了一个矩阵对象。我的意图是,矩阵作为对象的属性是不可变的,用多维数组实现。作为CCD_ 1。当我调用矩阵方法时。确保返回一个新的矩阵对象,应该深度复制为创建对象而传入的数组。

我在codewars中的一个测试中失败了,在这里,期望的双值与我调用toArray()方法时给出的值不同。但我不知道任何mroe信息,因为测试代码受到限制。

在下面的代码中,有人能看到我是否在其中创建了一个矩阵,其this.matrix属性可以从对象本身之外修改吗?

我尝试在构造函数中使用Arrays.copyOf,以确保为this.matrix属性创建新对象。我已经确保为每个方法返回一个新的Matrix对象。所以我真的不明白"this.matrix"实例变量在其他地方可能会被无意修改。

import java.util.Arrays;
@SuppressWarnings("WeakerAccess")
public class Matrix {
private double[][] matrix;
private int  rows;
private int columns;
//constructor for the already sorted array
Matrix(double[][] elements) {
if (elements == null) {
throw new IllegalArgumentException("Elements cannot be null");
}
int columns = elements[0].length;
for(double[] element: elements){
if(element == null){
throw new IllegalArgumentException("Element of 2D Array cannot be null");
}
if(element.length != columns){
throw new IllegalArgumentException("Array rows are not of equal length");
}
}
this.matrix = elements;
this.rows = this.matrix.length;
this.columns = columns;

}
/// given row_length, row_column
/// given list of elements
Matrix(int rows, int columns, double... elements) {
// remember double   ... elements means varargs
if(elements == null){
throw new IllegalArgumentException("Elements cannot be null");
}
if (elements.length != rows * columns) {
throw new IllegalArgumentException("Illegal number of rows and columns for elements given");
}
this.rows = rows;
this.columns = columns;
this.matrix = new double[this.rows][this.columns];
for(int i = 0; i<this.rows; i++){
//            System.arraycopy(elements, i*columns, this.matrix[i], 0, columns);
double[] row = Arrays.copyOfRange(elements, i*columns, (i+1) * columns);
this.matrix[i] = Arrays.copyOf(row,columns);
}
}
public double[][] toArray() {
return this.matrix;
///prints out the array to string
}
public Matrix multiply(double scalar){
// this will just multiply the matrix with the scalar
double[][] result = new double[this.rows][this.columns];
for(int i = 0; i < this.matrix.length; i++){
for(int j = 0; j < this.matrix[0].length; j++){
result[i][j] = this.matrix[i][j] * scalar;
}
}
return new Matrix(result);
}
public Matrix multiply(Matrix right){
double[][] right_mat = right.toArray();
//assert that left n = right m
if(this.columns != right.rows){
throw new IllegalArgumentException("Left matrix columns is not equal to Right matrix rows");
}
double[][] result = new double[this.rows][right.columns];

//loop through twice and incrememnt the additions
for(int m = 0; m < this.rows; m++){
for(int k = 0; k < right.columns;k++){
for(int n = 0; n < right.rows; n++){
result[m][k] += this.matrix[m][n] * right_mat[n][k];
}
}
}
return new Matrix(result);
}
public Matrix transpose(){
double[][] result = new double[this.columns][this.rows];
for(int i = 0; i < this.matrix[0].length; i++){
final int column = i;
// new_row should be column of existing
double[] new_row = Arrays.stream(this.matrix).mapToDouble(doubles -> doubles[column]).toArray();
result[i] = new_row;
}
return new Matrix(result);
}
public Matrix add(Matrix b){
///takes in Matrix adds to this one and
///returns the resulting Matrix
if(this.columns != b.columns || this.rows != b.rows){
throw new IllegalArgumentException("Matrices are not the same shape");
}
double[][] b_matr = b.toArray();
double[][] result = new double[this.rows][this.columns];
///Matrix needs to have the same number of rows and columns
for(int i= 0; i < this.rows; i++){
for(int j = 0; j < this.columns; j++){
result[i][j] = this.matrix[i][j] + b_matr[i][j];
}
}
return new Matrix(result);
}
}

首先,构造函数Matrix(double[][] array)不执行元素的深度复制。其次,toArray()方法应该返回this.matrix的深层副本,而不是该属性本身。

你可以像这样做阵列的深度复制

double[][] copy = new double[this.matrix.length][];
for (int i = 0; i < copy.length; ++i) {
copy[i] = new double[this.matrix[i].length];
for (int j = 0; j < copy[i].length; ++j) {
copy[i][j] = this.matrix[i][j];
}
}

最新更新