Java 返回的对象更改私有引用变量值

Java 返回的对象更改私有引用变量值,java,oop,Java,Oop,假设我有一个包含引用类型变量的类。我不希望该变量存储的对象的存储值能够更改,但我希望能够获取对象本身/访问其值。这需要将其私有化并创建一个getter,而不是setter。但是,这样做只会限制我更改变量指向的对象的能力,但不会阻止我更改对象本身的值 private void program(){ Test test = new Test(3); out.println(test.getA().a); // initial value, prints 3 test.g

假设我有一个包含引用类型变量的类。我不希望该变量存储的对象的存储值能够更改,但我希望能够获取对象本身/访问其值。这需要将其私有化并创建一个getter,而不是setter。但是,这样做只会限制我更改变量指向的对象的能力,但不会阻止我更改对象本身的值

private void program(){

    Test test = new Test(3);

    out.println(test.getA().a); // initial value, prints 3

    test.getA().a = 4; // changes referenced value through getter, even though the object is private, and has no setter

    out.println(test.getA().a); // changed value, prints 4

}

class Test{
    private A a;

    public Test(int a){
        this.a = new A(a);
    }

    public A getA(){
        return a;
    }
}

class A{
    public int a;

    public A(int a){
        this.a = a;
    }
}
在上面的代码中,我可以使用getter访问对象的值,即使我将变量设置为private以防止这种情况发生。我看到的唯一方法是创建一个新的对象,每次调用getter方法时都返回该对象,但对我来说,这似乎效率低下,因为它会占用内存中不必要的空间

是否有更好的方法来读取对象,同时仍然阻止更改或我遗漏了什么


提前感谢。

这是一个常见问题,有两种主要解决方案:

  • 您在getter中使用copy构造函数或clone()方法描述的方式
  • 您可以使A类不可变—只需将所有字段设为最终字段,并通过构造函数或嵌套生成器对其进行一次初始化即可
  • 我还建议不要将值类型字段公开

    有用链接:


    至于第二个解决方案,“a”属性应该可以更改,我只是不希望在测试类之外更改它。我将其设置为public就是为了这个例子,我意识到在实际代码中不应该将值类型字段设置为public。至于您的第一个解决方案,我前面的问题仍然存在:克隆对象不会占用不必要的空间吗?或者这只是解决问题的唯一方法吗?不,您不能仅通过引用一个特定类来编辑可变对象。当然,克隆还需要一些额外的处理器和内存资源。但若你们想修改测试类中的一个对象,为什么你们不能让它不可变,并在需要的时候用修改过的字段构建一个新的实例呢?它将解决性能问题。Getter应该比setter执行得更频繁。