如何在Java中实现将某些引用显式标记为“不需要的”?

如何在Java中实现将某些引用显式标记为“不需要的”?,java,garbage-collection,disposable,Java,Garbage Collection,Disposable,在我看来,我发现了一种情况,标准的垃圾收集算法不能很好地使用 假设我有一个对象A,它在构造时将自身添加为对象B事件的事件侦听器。由于对象具有将自身添加为侦听器所需的所有数据,因此它还具有将自身从侦听器中删除的数据 不幸的是,GC无法启动删除过程,因为在显式删除之前,对象将在侦听器列表中引用 因此,这意味着任何一个对象都不应该将自身添加为侦听器,或者应该有一种方法将某些引用标记为不重要。在后一种情况下,即使存在对对象的一些引用,GC也会启动垃圾收集——如果它们只是无关紧要的情况 显然,程序员必须清

在我看来,我发现了一种情况,标准的垃圾收集算法不能很好地使用

假设我有一个对象A,它在构造时将自身添加为对象B事件的事件侦听器。由于对象具有将自身添加为侦听器所需的所有数据,因此它还具有将自身从侦听器中删除的数据

不幸的是,GC无法启动删除过程,因为在显式删除之前,对象将在侦听器列表中引用

因此,这意味着任何一个对象都不应该将自身添加为侦听器,或者应该有一种方法将某些引用标记为不重要。在后一种情况下,即使存在对对象的一些引用,GC也会启动垃圾收集——如果它们只是无关紧要的情况

显然,程序员必须清除一些方法中所有不重要的引用,比如dispose或finalize

我理解,这种直接实现将是一种安全漂白剂。例如,若程序员违反了处理契约,垃圾收集将提供不正确的引用


因此,问题是:是否有一些库或模式来实现这种关系?

如果您只是希望管理对象生命周期以引用它,而不是作为侦听器,那么您可以将侦听器集合更改为类似于的“弱”集合。这样的集合用于避免在清除所有其他引用后使对象保持活动状态。

如果您只想将对象生命周期管理为引用它而不是作为侦听器,那么您可以将侦听器集合更改为类似的“弱”集合。这样的集合用于避免在清除所有其他引用后使对象保持活动状态。

查看Java中的不同子类。我想这就是您要寻找的

查看Java中的不同子类。我认为这就是您要寻找的

一般来说,当您希望对象被垃圾回收时,您应该将删除引用作为您的工作。这是在垃圾收集环境中管理内存的一部分

例如:

class MyInternalFrame extends JInternalFrame implements ActionListener {
    ...

    void removeSelfAndDispose() {
        for(JMenuItem button : parent.getMenuItems())
            button.removeActionListener(this);
        dispose();
    }
}
class MyInternalFrame extends JInternalFrame {
    ...

    MyInternalFrame() {
        for(JMenuItem button : parent.getMenuItems())
            button.addActionListener(new WeakListener(this, button));
    }

    static class WeakListener implements ActionListener {
        final Reference<JInternalFrame> ref;
        final AbstractButton button;

        WeakListener(JInternalFrame frame, AbstractButton button) {
            ref = new WeakReference<JInternalFrame>(frame);
            this.button = button;
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            JInternalFrame frame = ref.get();
            if(frame == null) {
                button.removeActionListener(this);
                return;
            }

            ...
        }
    }
}
但是,最好避免存储这些持久性引用。例如,使用静态嵌套类,而不是在容器上实现侦听器

可以使用来编造一个不阻止垃圾收集的侦听器,例如:

class MyInternalFrame extends JInternalFrame implements ActionListener {
    ...

    void removeSelfAndDispose() {
        for(JMenuItem button : parent.getMenuItems())
            button.removeActionListener(this);
        dispose();
    }
}
class MyInternalFrame extends JInternalFrame {
    ...

    MyInternalFrame() {
        for(JMenuItem button : parent.getMenuItems())
            button.addActionListener(new WeakListener(this, button));
    }

    static class WeakListener implements ActionListener {
        final Reference<JInternalFrame> ref;
        final AbstractButton button;

        WeakListener(JInternalFrame frame, AbstractButton button) {
            ref = new WeakReference<JInternalFrame>(frame);
            this.button = button;
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            JInternalFrame frame = ref.get();
            if(frame == null) {
                button.removeActionListener(this);
                return;
            }

            ...
        }
    }
}
但这是粗略的,不应该依赖。我们无法控制垃圾收集何时运行,因此这样做可能会导致不可预测的行为。我们保留引用的对象仍然存在,并在您认为它已被删除后响应事件


更可靠的方法是简单地防止不需要的引用被放置在适当的位置,或者在适当的时候故意删除它们。

通常,当您希望对象被垃圾收集时,您应该将删除引用作为您的工作。这是在垃圾收集环境中管理内存的一部分

例如:

class MyInternalFrame extends JInternalFrame implements ActionListener {
    ...

    void removeSelfAndDispose() {
        for(JMenuItem button : parent.getMenuItems())
            button.removeActionListener(this);
        dispose();
    }
}
class MyInternalFrame extends JInternalFrame {
    ...

    MyInternalFrame() {
        for(JMenuItem button : parent.getMenuItems())
            button.addActionListener(new WeakListener(this, button));
    }

    static class WeakListener implements ActionListener {
        final Reference<JInternalFrame> ref;
        final AbstractButton button;

        WeakListener(JInternalFrame frame, AbstractButton button) {
            ref = new WeakReference<JInternalFrame>(frame);
            this.button = button;
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            JInternalFrame frame = ref.get();
            if(frame == null) {
                button.removeActionListener(this);
                return;
            }

            ...
        }
    }
}
但是,最好避免存储这些持久性引用。例如,使用静态嵌套类,而不是在容器上实现侦听器

可以使用来编造一个不阻止垃圾收集的侦听器,例如:

class MyInternalFrame extends JInternalFrame implements ActionListener {
    ...

    void removeSelfAndDispose() {
        for(JMenuItem button : parent.getMenuItems())
            button.removeActionListener(this);
        dispose();
    }
}
class MyInternalFrame extends JInternalFrame {
    ...

    MyInternalFrame() {
        for(JMenuItem button : parent.getMenuItems())
            button.addActionListener(new WeakListener(this, button));
    }

    static class WeakListener implements ActionListener {
        final Reference<JInternalFrame> ref;
        final AbstractButton button;

        WeakListener(JInternalFrame frame, AbstractButton button) {
            ref = new WeakReference<JInternalFrame>(frame);
            this.button = button;
        }

        @Override
        public void actionPerformed(ActionEvent ae) {
            JInternalFrame frame = ref.get();
            if(frame == null) {
                button.removeActionListener(this);
                return;
            }

            ...
        }
    }
}
但这是粗略的,不应该依赖。我们无法控制垃圾收集何时运行,因此这样做可能会导致不可预测的行为。我们保留引用的对象仍然存在,并在您认为它已被删除后响应事件


更可靠的方法是简单地防止不需要的引用被放置在适当的位置,或者在适当的时候故意删除它们。

对于侦听器的特定情况,您应该在不再需要它们时删除它们。其他情况可能会使用弱引用或finalize,但对于通常不起作用的侦听器来说,对于侦听器的特定情况,您应该在不再需要它们时删除它们。其他情况可能使用弱引用或finalize,但对于侦听器来说,这通常不起作用。