是否存在使用弱引用而不是简单组合更好的情况?


10

虽然Java文档指定,即弱引用主要用于映射进行规范化,你会发现很多很多很多人在互联网上声称,该WeakHashMap中是完美的在其一生中存储的对象元数据。但是,没有人愿意做一个易于理解和适当的例子。

使用WeakHashMap向对象添加一些属性或存储元数据的声音对我来说,就像一个基于将要使用该死的东西的意愿的任意决定。换句话说-一个不好的设计。我了解,在某些情况下继承可能不可用(最终类,接口),但是组合又如何呢?我想不出一个例子,其中组合不是一种选择。当然,这是一个更好的选择,因为它依赖于公认的原则,而不是“语言怪癖”。

那么,有没有一种情况,使用弱引用而不是简单的组合会更好?如果没有,为什么互联网上的每个人似乎都会出错?


逻辑错误:“ ...基于只愿使用该死的东西的意愿而做出的任意决定。换句话说,是错误的设计。” 目的可能无法证明手段的合理性,但手段不足以使目的发生冲突。如果使用相同的方法,则结果可能是一个好的设计。虽然对于这种情况,我不会争论。:)
cwharris

3
弱引用是组成和继承的正交概念。
罗伯特·哈维

Answers:


13

假设我需要将一些元数据与一些数据对象相关联。这是一个很常见的情况。我不控制数据对象,并且有很多对象,有问题的API(回调,虚拟方法等)为我提供了这些数据对象,但没有我的元数据。因此,我需要为每个数据对象跟踪一些状态,即我之前见过并且可能再次见到的那些状态。我将此元数据称为装饰,这是有时用于该概念的术语。

简单的组合使您可以轻松地从装饰对象(一个带有元数据的对象)到另一个对象(一个带有数据的对象)查找,并假定我控制元数据对象的设计,因此可以在其中直接引用数据对象。

但是,除非您控制数据对象的设计并可以更改它,否则简单的组合不会提供反向查找(从数据对象到某些元数据)。实际上,除非您具有元数据对象的集合,否则就无法通过给定对象(数据)项来找到关联的元数据项。

除了从对象查找方向以查找其装饰元数据的问题外,还存在元数据生存期的问题。

即使不再使用数据对象,累积并永远不会释放的元数据是内存泄漏。

弱引用哈希图可以解决这两个问题。它允许定位给定数据的元数据,并允许在释放数据后的某个时间释放元数据。

还要注意,弱引用哈希映射不仅允许回收(元数据)值(gc'ed),而且还允许回收(数据)键(gc'ed),因为如果保留键,那么它也将是内存泄漏,而且,这些值也永远不会释放。


为什么不使用具有弱哈希映射支持的元数据表的数据对象作为组合?
杰克

2
@Jack,合成,尤其是至少在我看来是“简单的合成”,是指其他对象的对象,但直接如此。组成的“具有”关系使用简单的参考或有时使用集合来表示。在这里,哈希图是一种间接方法。如果没有哈希图,则无法到达装饰物。鉴于您可以进行此导航。因此,我更喜欢将此元数据称为装饰而不是组成,但是它们肯定是相关的。FWIW,装饰品(IMHO)确实与数据结合在一起,而并非相反。
Erik Eidt

@Jack,回复:我的最后一个FWIW,我刚刚意识到,使用弱哈希表时,由于内存占用(或者如果您确实想要在其中使用has-a),通常不会将元数据装饰对象的引用放置到另一个对象上方向,则必须是一个弱参考)。因此,通常,弱哈希图客户端使用两个对象,这些对象可以有效地配对,但从技术上讲,它们在对象组成上并不相互匹配。
Erik Eidt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.