Предположим, я подкласс JPanel
, и мой подкласс использует много памяти.
Как правильно спроектировать этот класс, чтобы освободить ресурсы памяти, когда мой JPanel используется в качестве компонента в более крупной системе?
Похоже, есть несколько вариантов:
- подкласс
finalize()
(красные флаги повсюду - литература, которую я читал, говорит, что вы не должны входить в завершающий бизнес)
- добавить явное
dispose()
или destroy()
или что-то еще, чтобы потребители моего класса использовали
- добавить своего рода слушателя в мою JPanel, который получит уведомление, когда родитель будет удален
- переопределить некоторый метод JPanel, который будет автоматически вызываться при удалении их родительского окна
В приведенном ниже примере я использовал опцию finalize()
, которая работает, но только когда вызывается сборщик мусора, и есть случаи, когда я предпочел бы очистку, когда JPanel больше не нужен.
Вариант № 2 хорош, но тогда я вынужден полагаться на то, что потребители будут вызывать этот метод, и философия Swing, похоже, просто вставляет компоненты в окно и позволяет всем компонентам разрушаться, когда окно закрывается. Поэтому, если мой JPanel находится внутри JTable в JScrollPane в JPanel в JFrame, скорее всего, потребитель моего класса не собирается вызывать мой метод 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);
}
}