【问题标题】:Java unable to serialize a objects which contain TreeMaps with ComparatorsJava 无法序列化包含带有比较器的 TreeMap 的对象
【发布时间】:2014-01-07 18:19:50
【问题描述】:

我有一个非常大的项目作为作业(针对 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,它们没有瞬态或静态字段(除了单例,它具有实例变量和 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());
            }
        });
    }
}

如果我只保留前 2 个 ArrayList,则序列化过程有效。 问题出在 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();
        }
    }
}

【问题讨论】:

  • 您有自定义比较器吗?如果是,那么您还必须序列化比较器。文档:docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
  • 我看到他的自定义比较器作为一个无名对象在 Central 类中..
  • @gtgaxiola 不,它是一个匿名比较器。
  • @SilentControl 相同的情况,如果它是匿名的,则不会被序列化...... JB Nizet 的答案是正确的。

标签: java exception serialization treemap notserializableexception


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    另一种强制ComparatorSerializable 的方法是将其转换为带有附加绑定强制转换的lambda:

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

    解释如下: Java lambda expressions, casting, and Comparators.

    【讨论】:

    • 我认为当时还没有 Java 8。
    • @SilentControl,也许吧。但是这些天人们也一直在寻找答案。 )
    【解决方案3】:

    将“implements Serializable”添加到您的比较器中,它应该可以解决问题。

    【讨论】:

    • 嗯,是的,这就是我所做的... 3 年前 xD。
    猜你喜欢
    • 2012-04-24
    • 1970-01-01
    • 2011-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    相关资源
    最近更新 更多