繁体   English   中英

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

[英]Java: how to store references to all instances of a class?

我更习惯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中没有析构函数,那么如何从列表中删除引用?
  • 如果没有删除引用,这些对象什么时候被垃圾收集?

简单的事情:除非使用非标准委托模式(使用自定义类加载器),否则多个类加载器不会导致问题。 如果您确实有这样的非标准类加载器,那么您可以获得应用程序的不同部分使用不同版本的CPPClass类(来自不同ClassLoader的每个版本)的情况。 这有各种各样的问题(你可以从CPPClassCPPClass获得一个ClassCastException转换!),但它不应该影响你的静态集合; 每个CPPClass都有自己独立的集合。

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

最后,核心问题。 如果每个对象不等于任何其他对象(即,如果您没有覆盖Object.equals ),则可以使用WeakHashMap ,将对象作为键。 如果类确实覆盖了equals ,则可以创建一个WeakReference集合,您可以在方便的时候剪切(在插入时,在检索列表时等)。 WeakReference不会阻止它引用的对象被GCed - 它只会在GC发生之后从get返回null

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

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

您确实可以将列表设置为静态,只需确保您也正确初始化它。

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM