Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不可变类如何分辨_Java_Class_Immutability - Fatal编程技术网

Java 不可变类如何分辨

Java 不可变类如何分辨,java,class,immutability,Java,Class,Immutability,我理解不可变意味着它是一个在实例化后不会改变状态的对象。但是在这一行代码中,我看不到数组值声明的最终结果。 这个类是不可变的吗?有人能解释一下如何找到答案吗。谢谢 public class A { private double[] values; public double[] getValues(){ return values; } } 是的,粘贴的代码没有任何关联的final关键字,也没有不可变的行为 我想提出一些与用java编写不可变类相关的关键准则: 1.)确保类不能被重写-使类成

我理解不可变意味着它是一个在实例化后不会改变状态的对象。但是在这一行代码中,我看不到数组值声明的最终结果。 这个类是不可变的吗?有人能解释一下如何找到答案吗。谢谢

public class A {
private double[] values;
public double[] getValues(){
return values;
 }
}

是的,粘贴的代码没有任何关联的final关键字,也没有不可变的行为

我想提出一些与用java编写不可变类相关的关键准则:

1.)确保类不能被重写-使类成为最终类,或使用静态工厂并保持构造函数私有

2.)将字段设置为私有和最终字段 强制调用者在一个步骤中完全构造一个对象,而不是使用无参数构造函数与对setXXX方法的后续调用相结合(也就是说,避免使用JavaBeans约定)

3.)不要提供任何可以以任何方式更改对象状态的方法-不仅仅是setXXX方法,还有任何可以更改状态的方法

4.)如果类有任何可变的对象字段,那么当它们在类和调用方之间传递时,必须对它们进行防御复制

A a = new A();
a.getValues()[0] = 1.2;
只要值不是空的,这就可以工作。但是,您将无法将值重新分配给新数组。即:
a.getValues()=newdouble[5]将不起作用


这个类不是不可变的,因为我可以更改值,只是不能重新分配它。

这里是一个简单的验证。这些值被初始化为1,2

使用getter和引用,可以在创建对象后更改数组中第一个项内的值

public class A {
    private double[] values;

    public double[] getValues() {
        return values;
    }

    public static void main(String[] args) {
        A test = new A();
        test.values= new double[]{1, 2};

        double[] valuesref = test.getValues();
        valuesref[0] = 10;

        for (int i = 0; i < test.values.length; i++) {

            System.out.println(test.values[i]);    
        }
    }
}
公共A类{
私人双重价值观;
public double[]getValues(){
返回值;
}
公共静态void main(字符串[]args){
A测试=新的A();
test.values=newdouble[]{1,2};
double[]valuesref=test.getValues();
值ref[0]=10;
对于(int i=0;i

如果getValues()返回数组的副本,则可以避免这种情况

正如其他人所写,该对象在其状态下被认为是可变的。它不可更改的是,您不能交换它所持有的数组。但是您可以更改数组的内容(getValues()[0]=10;)

要将其转换为不可变对象,必须使用列表而不是数组。有了List,您可以使用'method'将给定列表转换为可保存地公开给外部的版本。如果getValues()的调用方在不可修改的列表上使用add或remove,则会导致不支持的PertioneException,从而阻止修改对象保存

如果需要坚持使用阵列,则需要提供阵列的副本(System.arraycopy)或克隆(clone())

如果不能更改对象的属性(包括从超类继承的属性),则通常认为对象是不可变的。这通常也包括属性值,但这是一个模糊的定义


例如,如果您有一个类,其中包含一个指向文档文件的文件实例,而该文件实例无法更改,则该类被视为是不可变的(它提供的信息从未更改),但它指向的文档可以每次进行变异和更改。因此,它实际上是一条模糊的线(请记住,在您的示例中,您不能更改数组,只能更改数组的内容).

请参见java中字符串类的实现。不可变类的最佳示例。
final
在这里实际上没有帮助;问题在于它返回不可变数组而没有副本。您应该在公共类的属性上使用什么修饰符,以使属性(或方法)可以从任何包中的类的子类访问,但不能从不同包中的其他类访问?这是默认值吗?@Juan protected。默认修饰符允许同一包中的任何类访问它。protected是子类。不过,在再次阅读您的帖子后,听起来您需要某种这两个…@Cruncher-
protected
的混合允许任何包中的子类以及同一包中的任何代码进行访问。这是一种欺骗,因为
test.values=
在任何其他类中都不起作用。但我认为这证明了这一点,对吧,这样一个类的使用非常有限,它不起作用ve setters或非默认构造函数。只是想强调一个事实,即数组可以使用引用更改其值