如何防止改变变量的值

Oph*_*lia 14 java

我是Java的初学者。开发程序时,我创建了一个带有构造函数的对象,该构造函数以变量作为参数。但是当我在创建对象后更改变量的值时,我的对象具有第二个值而不是第一个值。我不希望我的对象更改值。我该怎么办?

public class Person {

    public Person(int[] arrayTest) {
            this.arrayTest = arrayTest;
    }

    public int[] getArray() {
        return this.arrayTest;
    }

    public boolean canHaveAsArray(int[] arrayTest) {
            return true;
    }

    private int[] arrayTest = new int[2];

    public static void main(String[] args) {
        int[] array = new int[] {5, 10};
        Person obj1 = new Person(array);
        array[0] = 20;
        System.out.println(Arrays.toString(obj1.getArray()));
    }
}
Run Code Online (Sandbox Code Playgroud)

我的输出应该是[5,10],但是我却得到[20,10]。即使如上所述更改数组的元素,我也需要获取[5,10]。我该怎么办?

Ani*_*wat 19

数组是通过Java中的引用传递的。如果将原始数组传递给的构造函数Person,则会将引用传递给原始数组。因此,arrayTest内部Person实例中的任何更改都将反映在原始array(int[] array)中,反之亦然。

如果您不想在Person实例中更改原始数组的元素的值,则有两个选择:

  • 您可以在Person构造函数中修改代码,以使用java.util.Arrays.copyOf方法创建原始数组的副本,然后使用该副本:

    public Person(int[] arrayTest) {
        this.arrayTest = java.util.Arrays.copyOf(arrayTest, arrayTest.length);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 不要将原始数组传递给构造函数,而只是发送原始数组的副本:

    Person obj1 = new Person(java.util.Arrays.copyOf(array, array.length));
    
    Run Code Online (Sandbox Code Playgroud)

但是,我更喜欢第一种方法。

  • 我同意这个答案。但是从这里陈述的两个选项来看,第一个选项应该是最合适的方法。原因是,无论何时您或其他人将要使用该代码,他们都不会犯问题中提到的错误。 (2认同)

Ste*_*n C 8

在Java中,没有不可变(不可更改)数组之类的东西。Java语言不支持此功能。正如JLS 4.12.4所述:

如果final变量持有对对象的引用,则可以通过对对象的操作来更改对象的状态,但变量将始终引用同一对象。这也适用于数组,因为数组是对象。如果final变量持有对数组的引用,则可以通过对数组的操作来更改数组的组件,但是变量将始终引用同一数组。

JVM规范也不支持不可变数组类型。您无法在语言级别解决此问题。避免更改数组的唯一方法是不与可能更改该数组的其他代码共享对该数组的引用。

在您的示例中,您具有所谓的泄漏抽象。您正在将数组传递给您的Person类,并且调用者保留对该数组的引用,以便可以对其进行更改。要解决此问题,您可以:

  • 复制数组,并将引用传递给副本,或者
  • 让构造函数(或array属性的setter)进行复制。

(有关示例代码,请参见答案/sf/answers/3879975011/。)

从面向对象的角度来看,第二种选择是更可取的。本Person类应该是负责从干扰保留其自己的内部状态......如果这是你的设计要求。它不应该依赖调用者来执行此操作。(即使呼叫方在技术上与此处的情况属于同一类,也是如此。)

  • 顺便说一下,关于泄漏抽象,Joel on Software上有一篇相关的博客文章https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/ (2认同)