7

我更习惯 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;

我应该如何在 Java 中做同样的事情?我有几个担忧:

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

3 回答 3

4

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

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

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

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

于 2013-04-09T16:10:54.707 回答
1

与其存储对对象的引用,不如存储对对象的WeakReference - 这样,如果 WeakReference 是唯一保留的引用,垃圾收集器将释放该对象。

于 2013-04-09T16:09:50.933 回答
0

您确实可以使列表静态,只要确保您也正确初始化它。

List<CPPClass> objlist;
static {
    objlist = new List<CPPClass>();
}

或者类似的东西应该这样做。

如果您不删除引用,它将永远不会被垃圾收集,因为垃圾收集器将假定该对象仍在使用中。

有一些东西看起来有点像析构函数:方法finalize。但是因为这个方法只被垃圾回收器调用,你不能自己使用,所以对你没有用。

于 2013-04-09T16:07:57.120 回答