【发布时间】:2011-05-31 15:03:17
【问题描述】:
假设我继承了JPanel,而我的子类占用了大量内存。
我设计这个类的正确方法是什么,以便在我的 JPanel 用作更大系统中的组件时释放内存资源?
似乎有几个选项:
- 子类
finalize()(到处都是危险信号——我读过的文献说你不应该进入最后的业务) - 添加明确的
dispose()或destroy()或其他任何内容,供我班的消费者使用 - 在我的 JPanel 中添加某种监听器,当父级被释放时会收到通知
- 覆盖 JPanel 的某些方法,当它们的父窗口被释放时会自动调用该方法
在下面的示例中,我使用了 finalize() 选项,该选项仅在调用垃圾收集时才有效,并且在某些情况下,我宁愿在不再需要 JPanel 时进行清理。
选项#2 不错,但是我必须依靠消费者来调用这个方法,而 Swing 的哲学似乎只是将组件粘贴到窗口中,并在窗口关闭时让所有组件销毁。因此,如果我的 JPanel 位于 JFrame 中的 JPanel 中的 JScrollPane 中的 JTable 中,那么我班级的使用者可能不会调用我的 dispose() 或 destroy() 方法。
选项 #3 或 #4 是我的选择,但我找不到任何似乎适用于此的内容。
有什么建议吗?
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class JPanelMemoryHog extends JPanel
{
final private String title;
final private Object space;
public JPanelMemoryHog(String title)
{
super();
this.title = title;
this.space = new byte[5*1000*1000];
setBorder(BorderFactory.createTitledBorder(title));
setPreferredSize(new Dimension(300,200));
}
@Override protected void finalize()
{
System.out.println("finalized "+this.title);
}
public static void main(String[] args) {
JFrame frame = new JFrame("example");
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JButton button = new JButton("create frame");
button.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
createFrame();
}
});
panel.add(button, BorderLayout.CENTER);
frame.setContentPane(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static int panelcount = 0;
protected static void createFrame() {
final String title = "panel"+(++panelcount);
final JFrame frame = new JFrame(title);
frame.setContentPane(new JPanelMemoryHog(title));
frame.pack();
frame.addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
System.out.println("closing "+title);
frame.dispose();
}
});
frame.setVisible(true);
}
}
【问题讨论】:
-
能否将面板添加到 JDialog 中?一旦对话框关闭,它应该确保您的面板默认被垃圾收集,没有任何特定的侦听器/事件/finialise()/destroy() 混乱。
-
@emeraldjava JDialog 完全不正确,第一个从来没有被 GC 处理过,但是隧道的光给了我们这个 Woodoo 由垃圾神为 JDialog stackoverflow.com/questions/5540354/…