Java中删除对象使后续访问报错的实现及置null无效的原因解析
Java对象删除问题解答
1. 为什么将f2引用设置为null后,仍然可以访问到原f2对象的data属性
- Java中的
f1、f2、f3都属于引用变量,仅存储堆空间中实际对象的内存地址,和堆中的对象本身是独立的。 - 初始化
f3时传入f2,本质是把f2当时存储的「data为23的bar对象的内存地址」直接赋值给f3.prev属性。此时f2和f3.prev是两个完全独立的引用,只是指向同一个堆对象。 - 执行
f2 = null仅会清空f2这个引用变量本身的值,不会修改f3.prev的指向,也不会直接删除堆中的目标对象。同时由于目标对象仍被f3.prev强引用,属于GC可达对象,垃圾回收器不会回收该对象,因此依然可以正常访问其属性。
2. 要正确删除该对象使得后续访问触发报错,该如何操作
你需要手动清除所有指向待删除对象的强引用,具体操作如下:
- 去掉
bar类中prev属性的final修饰,允许修改引用指向 - 找到所有持有待删除对象引用的位置,将对应引用赋值为
null。你当前场景中只有f3.prev持有目标对象的引用,直接修改该属性即可 - 如果是完整的双向链表场景,还需要同时修改待删除节点的前驱节点的next指针、后继节点的prev指针,彻底清除所有指向该节点的引用
修改后的可复现报错的代码如下:
public class prog { public static void main(String[] args) { bar f1 = new bar(12, null); bar f2 = new bar(23, f1); bar f3 = new bar(42, f2); f2 = null; // 清空f3持有的原f2对象引用 f3.prev = null; // 调用reveal时会抛出NullPointerException f3.reveal(); } } class bar { final int data; // 移除final修饰,允许修改prev指向 bar prev; bar(int data, bar prev) { this.data = data; this.prev = prev; } void reveal() { System.out.println("Value of this object is " + this.data); System.out.println("Value of Previous object is " + this.prev.data); } }
执行上述代码会触发Exception in thread "main" java.lang.NullPointerException,符合你要的报错效果。
内容的提问来源于stack exchange,提问作者tycoon
相关产品推荐
相关产品推荐

