我有一个相当大的项目作为作业(针对Uni的OOP课程):一个学校登记册,学生可以在那里查看自己的成绩,老师可以添加成绩等等。
"基本"类是一个单例,它包含所有使用的类(Java),例如一组用户、类(如在学校的类)和一个将类和教师与课程关联起来的TreeMap。
我想序列化这个基类(Central),以便保存修改后的数据。问题是我得到了这个异常
java.io.NotSerializableException: liceu.Central$1
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1183)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:440)
at java.util.TreeMap.writeObject(TreeMap.java:2265)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
at liceu.Main.main(Main.java:31)
我的所有类都实现了Serializable,并且它们没有瞬态或静态字段(除了singleton,它将实例变量和getInstance方法作为statics)。
因为发布的代码太多了(而且我会冒着在提交之前发布作业的风险),所以我试图通过隔离错误来证明概念。
public class Central implements Serializable
{
private ArrayList <User> users;
private ArrayList <Class> classess;
private TreeMap <Course, TreeMap <Class, Professor>> reunite;
private static Central instance = null;
private Central()
{
users = new ArrayList<>();
classess = new ArrayList<>();
reunite = new TreeMap<>(new Comparator<Student>(){
@Override
public int compare(Student e1, Student e2)
{
return e1.getName().compareTo(e2.getName());
}
});
}
}
如果我只保留前两个ArrayLists,那么序列化过程就可以工作了。问题出在树映射上。
TreeMap类是可序列化的吗?(一般而言)是因为匿名的Comparator吗?
这是具有序列化的主类
public class Main
{
public static void main(String args[])
{
Central cent = Central.getInstance();
FileOutputStream fos;
ObjectOutputStream oos;
cent.addUser(new Student(3,"id","pass","name","surname"));
cent.addUser(new Student(3,"id2","pass","name","surname"));
cent.addUser(new Student(3,"id1","pass","name","surname"));
try
{
fos = new FileOutputStream("save.txt");
oos = new ObjectOutputStream(fos);
oos.writeObject(cent);
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
TreeMap保存了一个对用于比较键的比较器的引用。比较器是一个不可序列化的匿名类的实例。所以你得到了这个例外。
将匿名比较器重新映射到顶层或命名的内部类,该类也实现Serializable。
强制Comparator
为Serializable
的另一种方法是通过附加的绑定强制转换将其转换为lambda:
TreeMap<Integer, String> sortedMap = new TreeMap<>(
(Comparator<Integer> & Serializable) (o1, o2) -> {
return o1.compareTo(o2);
}
);
以下是解释:Java lambda表达式、强制转换和比较器。
将"implements Serializable"添加到您的比较器中,它应该可以解决问题。