有什么好的方法可以让两个不可变的对象相互引用吗?

2022-09-03 13:06:56

以以下两个 Java 类为例:

class User {
   final Inventory inventory;
   User (Inventory inv) {
       inventory = inv;
   }
}

class Inventory {
   final User owner;
   Inventory (User own) {
       owner = own;
   }
}

有没有办法不使用反射*来实现这一目标?我实际上并不期望它是,但问它并没有什么坏处。

更新:由于在字节码构造中有两个步骤(1.分配对象,2.调用构造函数**),是否可以(ab)使用手写字节码或自定义编译器来执行此操作?我说的是首先对两个对象执行步骤 1,然后使用步骤 1 中的引用对两个对象执行步骤 2。当然,这样的事情会相当麻烦,而这部分问题是学术性的。

(*因为反射可能会给安全经理带来麻烦)

(**说我有限的知识)


答案 1

仅当其中一个对象由另一个对象创建时,这才能正常工作。例如,您可以将类更改为如下所示的内容(同时保持类不变):UserInventory

class User {
   private final Inventory inventory;
   User () {
       inventory = new Inventory(this);
   }
}

但是,在访问构造函数中的对象时需要小心:它尚未完全初始化。例如,其字段仍将是 !UserInventoryinventorynull

广告更新:我现在已经验证了字节码操作方法不起作用。我使用Jasmin尝试过它,但它总是无法加载VerifyError

深入研究这个问题,我发现了§ 4.10.2.4 实例初始化方法和新创建的对象。本节说明 JVM 如何确保仅传递初始化的对象实例。


答案 2

如果您不需要注入其中一个对象,则可以执行此操作。

class User {
   private final Inventory inventory;
   User () {
       inventory = new Inventory(this);
   }
}