Java OOP类getter/setter深拷贝实现优化方案及选型问询
完全不需要在你提到的两个方案里二选一,有更合理的实现方式,核心思路是拆分访问方法的职责,不要让同一个getter同时承担「内部逻辑复用的访问入口」和「对外安全暴露的接口」两个功能,同时优先优化类的不可变性,从根源降低拷贝开销。
具体实现方案
1. 优先把成员类改为不可变类
你当前示例里的A类存在changeNum修改方法,属于可变类,所以传递引用的时候有被外部修改的风险。如果业务允许,直接把A改成不可变类,所有成员变量加final修饰,移除修改方法,实例创建后就无法修改,这样不管是内部访问还是外部传递,都不需要做对象拷贝,完全没有额外开销。
改造后的A类代码:
public class A { private final int num; public A(int num) { this.num = num; } public A(A other) { this(other.num()); } // 移除changeNum修改方法,保证类不可变 public int num() { return this.num; } public int multiply(int multiply) { return this.num() * multiply; } }
2. 拆分对内、对外访问接口
把类的访问方法拆成两类:
- 私有对内访问方法:仅类内部调用,直接返回成员引用,不需要做拷贝,所有内部需要访问成员的逻辑统一走这个入口,保证后续要加访问逻辑时可以统一修改,实现复用。
- 公共对外访问方法:给外部调用使用,根据不可变性要求做拷贝或者返回不可变视图,保证内部状态不会被外部篡改。
改造后的B类代码:
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class B { private List<A> list; public B(List<A> list) { // 构造时仅做一次拷贝,避免外部传入的列表被修改影响内部状态 this.list = copyList(list); } public void changeList(List<A> list) { this.list = copyList(list); } // 对外暴露的公共getter,返回不可变视图(因为A已经是不可变类,不需要深拷贝) public List<A> list() { return Collections.unmodifiableList(this.internalList()); } public int sumMultiply(int multiply) { int sum = 0; // 内部调用私有访问方法,没有拷贝开销 for (A a : this.internalList()) { sum += a.multiply(multiply); } return sum; } // 私有对内访问方法,统一访问入口 private List<A> internalList() { return this.list; } private static List<A> copyList(List<A> list) { List<A> copyList = new ArrayList<A>(); for (A a : list) { copyList.add(new A(a)); } return copyList; } }
方案优势
- 既保留了类内部统一用访问方法、可以复用逻辑的好处,又避免了内部访问时不必要的深拷贝开销
- 对外依然严格保证不可变性,内部状态不会被外部意外修改
- 如果后续业务确实不允许把
A改为不可变类,也只需要修改对外的公共list()方法,把不可变视图改成深拷贝即可,内部逻辑完全不需要调整,性能损耗也只会出现在外部调用的场景,不会影响内部方法的执行效率。
内容的提问来源于stack exchange,提问作者jonatanE
相关产品推荐
相关产品推荐

