匿名类和父类之间的循环依赖是否错误?

Mic*_*udy 25 java anonymous-inner-class anonymous-class cyclic-reference

我有以下代码片段:

public class Example {

private Integer threshold;

private Map<String, Progress> history;

protected void activate(ComponentContext ctx) {
    this.history = Collections.synchronizedMap(new LinkedHashMap<String, Progress>() {
        @Override
        protected boolean removeEldestEntry(Map.Entry<String, Progress> entry) {
            return size() > threshold;
        }
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

Theres是匿名LinkedHashMap类和Example类之间的循环依赖.这样可以吗?为什么不?它会被垃圾收集器很好地收回吗?

aio*_*obe 22

这样可以吗?

这完全没问题.

threshold是一个字段,因此可以在匿名类中引用它而没有任何问题.(如果threshold是局部变量,则必须(有效)最终.)

类之间的循环依赖是常见的,当依赖图很小时(如本例所示),它不会造成任何问题.你LinkedHashMap是一个匿名课的事实并不重要.

它会被垃圾收集器很好地收回吗?

关于内存泄漏+内部类的唯一警惕是(非静态)内部类具有对其封闭对象的隐式引用.这意味着如果您创建了大量内部类的实例,则不能指望外部类对象的实例被垃圾回收.

在这种情况下,这意味着如果您泄漏对history地图的引用,Example则不会对GC进行实例化.


相关说明:

  • 考虑到你正在使用synchronizedMap它似乎你正在研究一个多线程程序.如果是这种情况,您需要对该threshold字段的同步和可见性问题保持警惕.

  • 如果可能的话,尽量让threshold场地最终

  • 另一种选择是为您创建一个命名类,LinkedHashMap并将其threshold作为该类中的字段包含在内.


Ser*_*nin 6

无论如何,你都有这种依赖,因为匿名内部类的每个对象都隐含了对封闭类对象的引用.Java是这样设计的,嵌套的内部类有这个参考是有原因的,所以从语言规范的角度来看,这会编译并看起来非常正常.

关于(缺少)"设计气味",如果这个匿名类对象完全封装在Example类中,没有独特的意义没有它的封闭上下文,并且不会泄露到Example类之外的任何地方,那么引用封闭字段没有任何问题类.您只需使用此内部类来组合一些逻辑.

但是,如果此对象从封闭对象中泄漏(例如,通过getter返回),则应禁止此操作或将其重构为threshold作为参数接收的静态内部类.此内部对象保存对封闭对象的引用,并可能使其远离GC,从而导致内存泄漏.