Java无法使用Comparators序列化包含TreeMaps的对象

Sil*_*rol 2 java serialization exception treemap notserializableexception

我有一个相当大的项目(大学的OOP课程):一个学校注册,学生可以看到他们的成绩,教师可以增加成绩等等.

"base"类是一个包含所有使用的类(Java)的单例,例如用户数组,类(如在学校类中)和将classess和教师关联到课程的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)
Run Code Online (Sandbox Code Playgroud)

我的所有类都实现了Serializable,它们没有瞬态或静态字段(单例除外,它具有实例变量和getInstance方法作为静态).

因为发布会有很多代码(我会冒着通过在提交之前发布它来使我的作业无效),我试图通过尝试隔离错误来进行概念验证.

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());
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我只保留前2个ArrayLists,则序列化过程有效.问题出在TreeMap上.

TreeMap类是否可序列化?(一般情况下)是不是因为匿名比较器?

这是序列化的主类

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

JB *_*zet 13

TreeMap保存对用于比较键的比较器的引用.比较器是一个不可序列化的匿名类的实例.所以你得到了这个例外.

将匿名比较器重构为顶级或命名内部类,它也实现Serializable.


Vad*_*zim 6

给力的另一种方法ComparatorSerializable将它与另外结合投转换为拉姆达:

TreeMap<Integer, String> sortedMap = new TreeMap<>(
    (Comparator<Integer> & Serializable) (o1, o2) -> {
        return o1.compareTo(o2);
    }
);
Run Code Online (Sandbox Code Playgroud)

这是解释: Java lambda 表达式、强制转换和比较器

  • @SilentControl,也许吧。但如今人们也在不断寻找答案。) (2认同)