所以最近我正在为我们这里开发一个工具来配置某些应用程序。它不需要非常棒的东西,只是一个带有一些 SQL 脚本生成的基本工具,并创建了几个 XML 文件。在此期间,我使用自己的 AbstractTableModel 实现创建了一系列 JTable 对象。在我构建完所有内容并使用 AbstractTableModel(刚刚使用 ObjectStreamWriter 写入磁盘)测试保存和加载之后,序列化失败了。我几乎花了一整天的时间才弄清楚发生了什么。当我尝试序列化它们时,我会在 java.lang.reflect.Constructor 上得到 NotSerializableException。我不知道这是怎么回事,因为我的表模型只包含可序列化的实体,而我附加的所有侦听器也是可序列化的,并且父类也是可序列化的。经过大量挖掘和一些有用的帖子后,我发现当您将 TableModelListener 添加到 AbstractTableModel 实现时,除了您添加的侦听器之外,还会添加另一个侦听器,其类型为 javax.swing.event.TableModelListener,它不是t 可序列化(见http://docs.oracle.com/javase/7/docs/api/javax/swing/event/TableModelListener.html的接口,我不知道实现)。编辑模型不会添加这个不可序列化的侦听器,JTable 会。我的问题本质上是,为什么这个对象会在内部添加自己的不可序列化对象,从而否定它实际上实现了可序列化的事实?这是我应该报告为错误的东西吗?
仅供参考,我的工作是简单地删除所有侦听器,序列化,然后重新添加侦听器。反序列化时,我只需要添加我创建的一个,模型再次自己创建另一个。
编辑尝试使用通过调用 setValueAt() 方法提供的序列化程序类序列化此模型。
import java.io.Serializable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
public class BlankTableModel extends AbstractTableModel implements Serializable {
/**
*
*/
private static final long serialVersionUID = 6063143451207205385L;
public BlankTableModel()
{
this.addTableModelListener(new InnerTableModelListener());
}
@Override
public void setValueAt(Object o, int x, int y)
{
this.fireTableChanged(new TableModelEvent(this, x, y));
}
public int getColumnCount() {
// TODO Auto-generated method stub
return 2;
}
public int getRowCount() {
// TODO Auto-generated method stub
return 2;
}
public Object getValueAt(int arg0, int arg1) {
// TODO Auto-generated method stub
return "Test Data";
}
private void save()
{
Serializer.SerializeObject(this);
}
@Override
public boolean isCellEditable(int rowindex, int colindex)
{
return true;
}
private class InnerTableModelListener implements TableModelListener, Serializable
{
@Override
public void tableChanged(TableModelEvent arg0) {
save();
}
}
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Serializer {
public static void SerializeObject(Serializable object)
{
File out = new File("USE A VALID PATH");
if (!out.exists())
{
try {
out.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
}
else
{
out.delete();
try {
out.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try (FileOutputStream fos = new FileOutputStream(out);
ObjectOutputStream oos = new ObjectOutputStream(fos))
{
oos.writeObject(object);
}catch (Exception e)
{
e.printStackTrace();
}
}
}
然后尝试用这个替换保存方法
private void save()
{
for (TableModelListener l : this.getTableModelListeners())
{
this.removeTableModelListener(l);
}
Serializer.SerializeObject(this);
this.addTableModelListener(new InnerTableModelListener());
}
这是一个简单的 gui
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JTable;
public class MainForm extends JFrame {
public static void main(String[] args)
{
MainForm form = new MainForm();
form.show();
}
public MainForm()
{
this.setBounds(100, 100, 600, 600);
BlankTableModel model = new BlankTableModel();
JTable table = new JTable(model);
table.setPreferredSize(new Dimension(500,500));
this.getContentPane().add(table);
}
}