LinkedHashMap 的子类作为缓存

Subclass of LinkedHashMap as cache

在 java 库中 LinkedHashMap 有一个方法

protected boolean removeEldestEntry(Map.Entry<K,V> eldest)

有描述

Returns true if this map should remove its eldest entry. ... This is useful if the map represents a cache

因此,LinkedHashMap 具有可用于创建缓存的受保护方法。

像这样:

public final class LinkedHashMapCache<K, V> extends LinkedHashMap<K, V> {
  private final int MAX_LENGTH = 1000;

  @Override
  protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
    return size() > MAX_LENGTH;
  }
}

但是我的 IDE (IntelliJ IDEA) 使用检查消息突出显示了我的代码:

Class 'LinkedHashMapCache' explicitly extends 'java.util.LinkedHashMap'

IDE 用于检查的内部名称(例如在忽略它时使用,在其 XML 配置文件中使用)是 ClassExtendsConcreteCollection,标题和描述是:

Class explicitly extends a Collection class

Reports any clases which extend concrete classes of type java.util.Collection or java.util.Map. Subclassing collection types is a common practice of novice object-oriented developers, but is considerably more brittle than delegating collection calls.

问题:将 LinkedHashMap 子类化并禁止检查是个好主意吗?或者我需要其他解决方案?

我真正的 removeEldestEntry 方法确实比示例中的要复杂,我不仅需要检查地图的大小,还需要检查实体值中的一些变量。 所以,我需要自定义(但简单)缓存。

这次检查的文字其实并没有说明真正的危险。

扩展集合 classes 的真正危险是例如忽略重写 all 方法。例如,在扩展 Map 具体实现时,您覆盖了 .put() 而不是 .putAll() ;没有任何东西可以保证您扩展的 class 将使用 .put() 作为“.putAll() 后端”,因此您应该覆盖两者。

不过在你的情况下,你没有这样的担心。

然而,检查是正确的,扩展比委托更 "brittle"。事实上,Guava 有很多 classes 专用于 "collection delegation",默认委托:ForwardingMapForwardingList 等等;然后你只覆盖你需要的方法 "delegator".

我认为这个建议一般来说可能是好的,但不适用于 LinkedHashMap,因为受保护的方法清楚地表明这个 class 是为 subclassing

设计的