gpt4 book ai didi

java - Java中getter的访问安全

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:19:36 26 4
gpt4 key购买 nike

因此,我们创建了一个带有一些私有(private)类成员的简单类,并为其自动生成了 getter。但 getter 实际上返回了对该成员的引用,从而获得了对私有(private)成员的完全访问权限。可以吗?这是一个类的代码:

public class User {

private ArrayList<String> strings = new ArrayList(){ {
add("String1");
add("String2");
} };

public User() {
}

public ArrayList<String> getStrings() {
return strings;
}

public void setStrings(ArrayList<String> strings) {
this.strings = strings;
}
}

主要方法代码:

    public class Main {
public static void main(String[] args){
User user = new User();

System.out.println(user.getStrings());
user.getStrings().add("String3");
System.out.println(user.getStrings());
}
}

并输出:

[字符串 1, 字符串 2]

[字符串 1、字符串 2、字符串 3]

我已经将 getter 更改为这个:

public ArrayList<String> getStrings() {
return (ArrayList<String>)strings.clone();
}

但问题仍然存在, setter/getter 如果不是为了安全,还有什么用?正确的写法是什么?

最佳答案

不,这不行,因为它破坏了封装,因此该类无法维护自己的不变量。与构造函数相同。

但问题不在于 getter/setter,而在于自动生成它们的代码。

长话短说:不要盲目地使用自动生成的访问器,如果他们正在处理可变结构,请制作防御性副本(或不可变的等价物)。


顺便说一句,我不会有返回类型为 ArrayList 的 getter,即使它只是一个副本。您返回什么样的列表通常与客户无关,所以我的 getter 看起来像这样:

public List<String> getStrings() {
return new ArrayList<>(strings);
}

或者使用不可变 View :

public List<String> getStrings() {
return Collections.unmodifiableList(strings);
}

或者使用 Guava 的 ImmutableList 类:

public List<String> getStrings() {
return ImmutableList.copyOf(strings);
}

三种解决方案之间存在细微差别,因此最佳解决方案可能会有所不同。作为一般规则,我更喜欢返回不可变结构,因为这清楚地表明不会反射(reflect)对结构所做的更改,即 user.getStrings().add( "X"); 将失败一个异常(exception)。


您向我们展示的代码的另一个微妙问题是双括号初始化。想象这样一个类:

public class Foo {
private List<String> strings = new ArrayList() {{ add("bar");}};
private Object veryLargeField; //the object stored here consumes a lot of memory

public List<String> getStrings() {
return strings;
}
}

现在假设我们正在这样做:

private class Bar {
private List<String> fooStrings;

public Bar() {
this.fooStrings = new Foo().getStrings();
}
}

Bar 会消耗多少内存(或者使用准确的术语:保留)?好吧,事实证明很多,因为你对双括号初始化所做的是创建一个匿名内部类,它将包含对其外部类 (Foo) 的引用,因此当返回的列表是可访问的,Foo 的所有其他字段将不符合垃圾收集条件。

关于java - Java中getter的访问安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30422558/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com