Java:如何存储对类的所有实例的引用?

Edu*_*rra 7 java static garbage-collection

我更习惯C++.要获取类的所有实例的列表(这是一个可以由用户扩展的库类),我通常有一个静态容器,其中包含对这些对象的所有引用:

#include <list>
class CPPClass;

class CPPClass {
   public:
   CPPClass() {
      objList.push_back(this);
   }
   ~CPPClass() {
      objList.remove(this);
   }

   private:
   static std::list<CPPClass *> objList;
};

std::list<CPPClass *> CPPClass::objList;
Run Code Online (Sandbox Code Playgroud)

我应该如何在Java中做同样的事情?我有一些顾虑:

  • 有人向我提到可能有多个类加载器,这可能会导致问题
  • java中没有析构函数,那么如何从列表中删除引用?
  • 如果没有删除引用,这些对象什么时候被垃圾收集?

ysh*_*vit 4

首先简单的事情:多个类加载器不会给您带来问题,除非您使用非标准委托模式(使用自定义类加载器)。如果您确实有这样的非标准类加载器,则可能会出现应用程序的不同部分使用该类的不同版本CPPClass(每个版本来自不同的类加载器)的情况。这有各种问题(您可以ClassCastExceptionCPPClassto进行转换CPPClass!),但它不应该影响您的静态集合;每个CPPClass都有自己独立的收藏。

接下来的事情:不要从构造函数将对象添加到集合中。从构造函数泄漏this引用可能会导致内存模型问题。相反,您应该创建一个静态工厂方法来创建对象,然后将其单独添加到静态集合中。当然,该集合也应该是线程安全的。

最后,核心问题。如果每个对象不等于任何其他对象(即,如果您没有覆盖Object.equals),则可以使用 Wea ​​kHashMap,并将对象作为键。如果类确实 override ,您可以创建WeakReferenceequals的集合,您可以在方便的时候(在插入时、检索列表时等)对其进行修剪。WeakReference 不会阻止它引用的对象被 GC 处理——它只会在 GC 发生后返回。nullget

但如果我可以稍微编辑一下,像这样的“解决方案”通常暗示着定义不明确的对象生命周期,这还有其他可维护性问题。Closeable如果您的对象实现或具有类似的方式来使用它们来声明已完成它们的代码,那可能会更好。