Java中如何关联字段,实现关联对象ID变更时自动同步对应字段值?
Java中关联id自动同步的实现说明
核心认知
Java原生赋值语义无法实现类似a = b后a随b自动更新的效果,本质原因是Java为值传递机制:
- 对
Long这类不可变值类型字段赋值时,传递的是具体值/不可变对象的引用拷贝,而非对可变存储位置的绑定 - 直接执行
s.setId(c.getId())时,是将当前时刻c.id对应的Long值拷贝存入s的id字段,后续c的id引用指向新值时,s字段存储的拷贝值不会发生变化
可行的无手动同步实现方案
动态取值替代静态存值
直接去掉关联类中冗余的id存储字段,将其改为对源对象的弱引用绑定,获取id时动态读取源对象的最新值,从根源避免值拷贝带来的不同步问题:import java.lang.ref.WeakReference; class Student { // 存储关联Class对象的弱引用,避免内存泄漏 private WeakReference<Class> relatedClassRef; // 重写id获取逻辑,动态返回关联Class的最新id public Long getId() { Class relatedClass = relatedClassRef == null ? null : relatedClassRef.get(); return relatedClass == null ? null : relatedClass.getId(); } // 绑定关联Class,替代原来的id赋值操作 public void bindRelatedClass(Class c) { this.relatedClassRef = new WeakReference<>(c); } } class Class { private Long id; public Long getId() { return id; } public void setId(Long id) { this.id = id; } }绑定完成后,只要关联Class的id发生变更,调用
Student.getId()即可拿到最新值,无需手动同步赋值。变更监听机制触发自动同步
给id会发生变更的源对象增加变更回调能力,源对象id修改时主动触发所有关联对象的id更新逻辑:import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; class Class { private Long id; // 线程安全的变更监听器列表 private final List<Runnable> idChangeListeners = new CopyOnWriteArrayList<>(); public Long getId() { return id; } public void setId(Long id) { this.id = id; // 触发所有注册的监听器,执行关联对象的同步逻辑 idChangeListeners.forEach(Runnable::run); } // 供关联对象注册同步回调的方法 public void addIdChangeListener(Runnable listener) { idChangeListeners.add(listener); } } // 原有Student类保留原始结构,无需改造: // class Student { // private Long id; // public Long getId() {return id;} // public void setId(Long id) {this.id = id;} // }绑定关联关系时,直接将同步逻辑注册为监听器即可:
Student s = new Student(); Class c = new Class(); // 注册同步逻辑,c的id变更时自动执行s的id赋值 c.addIdChangeListener(() -> s.setId(c.getId()));
可行性结论
上述两种方案均可以实现无需手动重复赋值的同步效果,没有语法层面的实现阻碍,仅需要对原有类的字段逻辑做一定改造,无法达到和原生简单赋值完全一致的零成本书写体验。
内容的提问来源于stack exchange,提问作者Самир Шахмурадлы
相关产品推荐
相关产品推荐

