java - 将 Finalize() 与装饰模式一起使用

标签 java decorator backwards-compatibility

我有一个设计问题正在尝试解决。简而言之,是否可以使用 Finalize() 来释放仅与该对象相关且仅在该对象存在期间可用的私有(private)静态资源?详情如下...

首先是限制:

  1. 我正在使用装饰器模式来封装我想要的类型 (X) 没写

  2. Xfinal,因此不可能对其进行子类化。

  3. 我在包装器中有一个方法,例如 x(),它随时都会 返回底层的X实例

  4. x() 的原因是包装类型需要是 与需要 X 的现有 API 互换兼容 参数

  5. 包装器有一个构造函数,它将 X 实例作为 范围。然后它将其封装的 X 对象设置为此 实例。

问题:

我想在包装器中添加一些功能/数据,将其保留。我的意思是,当包装器“解包”到 X 时,它可以在代码中的其他点“重新包装”到包装器,嘿,很快,额外的数据甚至会被恢复尽管它没有在底层 X 中携带。

到目前为止我的想法:

如果我在包装类中创建一个静态映射,其中键是唯一的 X id,值是某种结构中的额外数据,那么我可以在 中检索它让我们说一下 rewrap(X x) 方法。

我不会使用包装器或X对象作为映射中的键,因为这将阻止它被GC(除非明确从映射中删除),所以我们'将使用唯一的哈希码。

虽然原则上这似乎没问题,但问题是何时从静态 map 中删除这些额外数据。在这种情况下,我们可以允许执行finalize()吗:

finalize(){
   map.remove(wrapperKey);
}

这是我的理由...我们都知道,一般而言,依赖于 Finalize() 来释放资源是一个坏主意,但这里所讨论的资源直接与对象相关。没有对外部资源的引用,因此我们需要这些内部资源,直到包装对象本身被 GC 为止,此时我们只需删除资源映射即可。

最坏的情况是不用担心删除这些冗余的静态映射,因为这会导致内存泄漏。

我想不出任何其他方法来实现此功能并保持与现有 API 的向后兼容性:

public void foo(Wrapper wrapper){
  bar(wrapper.x());
}
public void bar(X instance){...}

这就是问题所在,还有其他方法或意见吗?

非常感谢

编辑: 经过进一步研究,我想我会更新这个问题,因为类似的情况可能是weak references的主要候选者。

最佳答案

如果每次需要访问 X 实例时显式调用 Wrapper.x,难道不能向 Wrapper 添加清理方法并在删除 Wrapper 对象之前显式调用该方法吗?

清理方法也可以从finalize调用,以确保它在没有被显式调用的情况下得到清理。这将为您带来两全其美的效果,因为如果包装器使用不当,您将有更大的机会减少内存泄漏。

void someRandomMethod() {
    Wrapper someWrapperINeed = new Wrapper(new X(blah, blah blah));
    foo(someWrapperINeed);
    someWrapperINeed.clean();

    // Instead of foo(new Wrapper(new X(blah, blah, blah));
}

// Or foo can call clean if the wrapper will never be needed after its invocation
void foo(Wrapper w) {
    bar(w.x());
    w.clean();
}

编辑:添加代码示例!

关于java - 将 Finalize() 与装饰模式一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14137481/

相关文章:

java - 类层次结构爆炸

python - 将生产中的所有 python 包升级到最新版本是一个好习惯吗?

android - Material Design 向后兼容性

java - 当我添加 "this"时,递归初始化程序有效吗?

python - 了解 python 内存装饰器中的参数处理

java - 使用 Maven 将资源文件夹下的文件添加到 zip

python - 你将如何在 python 中编写 @debuggable 装饰器?

c# - 始终从 GAC 获取最新的 dll

java - 将一系列 BufferedImages 转换为 Java 中的视频?

java - Maven - 安装公共(public)存储库中不可用的 JAR(在 Eclipse 中)