简体   繁体   English

Java Create Wrapper类与可变成员不可变

[英]Java Create Wrapper Class Immutable with Mutable members

currently I have a class called MatrixValue that I want to make into an immutable object so that all my methods that interact with an instance of MatrixValue can't change its inner matrix. 目前,我有一个名为MatrixValue的类,我想将该类做成一个不可变的对象,以便与MatrixValue实例进行交互的所有方法都不能更改其内部矩阵。 However, the problem is one of the member variables is a mutable object called RealMatrix that stores all the actual data of the matrix. 但是,问题是成员变量之一是一个称为RealMatrix的可变对象,该对象存储矩阵的所有实际数据。 I've already put in defensive copying into the constructor and gotten rid of any mutator methods. 我已经将防御性复制放入构造函数中,并且摆脱了任何mutator方法。 Here is what my class looks like so far: 到目前为止,这是我班上的样子:

public final class MatrixValue extends ExpressionValue{

    /**
     * 
     */
    private static final long serialVersionUID = -4231050452116360135L;
    private final RealMatrix matrix;

    public MatrixValue(RealMatrix matrix){
        this.matrix = new Array2DRowRealMatrix(matrix.getData());
    }

    public MatrixValue(double[][] values){
        matrix = new Array2DRowRealMatrix(values);
    }

    public RealMatrix getMatrix() {
        return matrix;
    }

    @Override
    public String toString(){
        return matrix.getRowDimension() + "," + matrix.getColumnDimension();
    }
}

The problem right now is that if someone calls matrixValue.getMatrix().setEntry(row, col, value); 现在的问题是,如果有人调用matrixValue.getMatrix().setEntry(row, col, value); they are effectively able to change the value of the final RealMatrix member variable. 他们可以有效地更改最终RealMatrix成员变量的值。 However, I still want to be able to return information regarding the RealMatrix . 但是,我仍然希望能够返回有关RealMatrix信息。 What's the best approach to fixing this hole in the class's immutability? 解决此类不变性的最佳方法是什么?

EDIT : Also do keep in mind that some matrices can become memory intensive so if possible I would prefer a solution that minimizes duplicating unnecessary information if possible. 编辑 :还请记住,某些矩阵可能会占用大量内存,因此,如果可能的话,我希望使用一种解决方案,以最大程度地减少不必要信息的重复。

Consider using an interface on RealMatrix. 考虑在RealMatrix上使用接口。 A possible interface might be called Matrix. 可能的接口可能称为矩阵。 You internals representation could then use RealMatrix and then where you provide your external API you can instead of using the return type of RealMatrix return a Matrix instead. 然后,您的内部表示形式可以使用RealMatrix,然后在提供外部API的地方,可以代替使用RealMatrix的返回类型,而返回Matrix。

class RealMatrix implements {
// getters and setters
}

interface Matrix  {
// only getters
}

The simplest way to do probably is to return a defensive copy of matrix from the getMatrix() method. 最简单的方法可能是从getMatrix()方法返回matrix的防御性副本。 You may clone it every time and return in the method or make a copy in the constructor and only return the same copy in the method. 您可以每次克隆它,然后在方法中返回,或者在构造函数中创建一个副本,然后仅在方法中返回相同的副本。

However, I would think what the intention of MatrixValue is. 但是,我认为MatrixValue的意图是什么。 If it is an immutable representation of RealMatrix , I would consider to compose an interface for RealMatrix and MatrixValue as follows: 如果它是RealMatrix的不可变表示RealMatrix ,我将考虑为RealMatrixMatrixValue组成一个接口,如下所示:

interface Matrix {
  // getters for Matrix
}

RealMatrix and MatrixValue will implement the interface as follows: RealMatrixMatrixValue将实现以下接口:

public class RealMatrix implements Matrix {
    // getters for Matrix
    // setters for RealMatrix
}

public class MatrixValue extends ExpressionValue implements Martix {
    public MatrixValue(RealMatrix matrix){
        this.matrix = new Array2DRowRealMatrix(matrix.getData());
    }

    // getters for Matrix
}

This provide the intention that RealMatrix and MatrixValue are mutable and immtable representation of Matrix correspondingly and allow API callers to get the values from MatrixValue but cannot modify it. 这提供了这样的意图,即RealMatrixMatrixValue分别是Matrix可变和不可固定的表示形式,并允许API调用者从MatrixValue获取值,但不能对其进行修改。

By the way, create a new instance of Array2DRowRealMatrix in MatrixValue constructor may not enough to do a defensive copying because the array of double[][] can be modified externally. 顺便说一下,在MatrixValue构造函数中创建Array2DRowRealMatrix的新实例可能不足以进行防御性复制,因为double[][]数组可以在外部进行修改。 You need to make a copy of the array using Arrays.copyOf or System.arraycopy for each dimension of the array to avoid mutation. 您需要使用Arrays.copyOfSystem.arraycopy为数组的每个维度制作数组的副本,以免发生突变。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM