Java对象在序列化时丢失所有数据

时间:2018-09-19 07:00:30

标签: java serialization

import java.io.*;
import java.util.StringTokenizer;


interface IFileIO {
    void writeTo(String f);
    void readFrom(String f);
}

class TextDoctor extends Doctor implements IFileIO {
    @Override
    public void readFrom(String f) {
        try {
            FileReader fr = new FileReader(f);
            BufferedReader br = new BufferedReader(fr);
            String s = br.readLine();
            try {
                StringTokenizer st = new StringTokenizer(s);
                setName(st.nextToken());
                setExp(Integer.parseInt(st.nextToken()));
                setApps(new AbstractAppointment[Integer.parseInt(st.nextToken())]);
                for (int i = 0; i < getApps().length; i++) {
                    s = br.readLine();
                    st = new StringTokenizer(s);
                    getApps()[i] = new Appointment();
                    getApps()[i].setDay(Integer.parseInt(st.nextToken()));
                    getApps()[i].setPatients(Integer.parseInt(st.nextToken()));
                    getApps()[i].setComment(st.nextToken());
                }
            }
            finally {
                br.close();
            }
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void writeTo(String f) {
        try {
            FileWriter fw = new FileWriter(f);
            PrintWriter pw = new PrintWriter(fw);
            pw.println(getName() + ' ' + getExp() + ' ' + getApps().length);
            for (AbstractAppointment a : getApps()) {
                String out = Integer.toString(a.getDay()) + ' ' + Integer.toString(a.getPatients()) + ' ' + a.getComment();
                pw.println(out);
            }
            pw.close();
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public TextDoctor(String name, int exp, AbstractAppointment... apps) {
        super(name, exp, apps);
    }

    public TextDoctor() {
    }
}

class SerialDoctor extends Doctor implements IFileIO, Serializable {
    private static final long serialVersionUID = -1259966276768081694L;

    @Override
    public void writeTo(String f) {
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f))) {
            out.writeObject(this);
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void readFrom(String f) {
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(f))) {
            SerialDoctor doc = (SerialDoctor) in.readObject();
            setName(doc.getName());
            setExp(doc.getExp());
            setApps(doc.getApps());
        }
        catch (IOException | ClassNotFoundException ex) {
            ex.printStackTrace();
        }
    }

    public SerialDoctor(String name, int exp, AbstractAppointment... apps) {
        super(name, exp, apps);
    }

    public SerialDoctor() {
    }
}


public class task1 {
    public static void main(String[] args) {
        TextDoctor tdoc = new TextDoctor();
        tdoc.readFrom("input.txt");
        tdoc.sortAppsByPatients();
        System.out.println("input.txt (sorted by patients):");
        System.out.println(tdoc);
        for (AbstractAppointment a : tdoc.getApps()) {
            System.out.println(a);
        }
        tdoc.writeTo("output.txt");

        SerialDoctor sdoc = new SerialDoctor();
        sdoc.setName(tdoc.getName());
        sdoc.setExp(tdoc.getExp());
        sdoc.setApps(tdoc.getApps());

        sdoc.writeTo("input.dat");
        SerialDoctor sdoc2 = new SerialDoctor();
        sdoc2.readFrom("input.dat");
        sdoc2.sortAppsByComment();
        System.out.println("input.dat (sorted by comments):");
        System.out.println(sdoc2);
        for (AbstractAppointment a : sdoc2.getApps()) {
            System.out.println(a);
        }
        sdoc2.writeTo("output.dat");

    }
}

我有一个类型为SerialDoctor的对象,该对象是可序列化的,需要序列化为input.dat以后再读入另一个SerialDoctor对象。 SerialDoctor继承字段String nameint expAbstractAppointment[] apps,这是我另一个类的对象的数组(不实现Serializable)。问题在于,序列化Java时,我只写类元数据(我想是吗?),而没有在文件中存储实际的类数据,反序列化时exp为0,nameapps为null,因此尝试使用数据(丢失的数据)会产生NullPointerException。以下是Serial Doctor扩展的类:

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

abstract class AbstractAppointment implements Comparable<AbstractAppointment> {

    abstract public int getDay();
    abstract public int getPatients();
    abstract public String getComment();

    abstract public void setDay(int day);
    abstract public void setPatients(int patients);
    abstract public void setComment(String comment);

    @Override
    public String toString() {
        return "Day: " + getDay() + ", patients: " + getPatients() + ", comment: " + getComment();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || !(obj instanceof AbstractAppointment)) {
            return false;
        }
        AbstractAppointment a = (AbstractAppointment) obj;
        return (getDay() == a.getDay()) && (getPatients() == a.getPatients()) && (getComment() == a.getComment());
    }


    public int compareTo(AbstractAppointment o) {
        return Integer.compare(getPatients(), o.getPatients());
    }
}

class Appointment extends AbstractAppointment{
    private int day;
    private int patients;
    private String comment;

    @Override
    public int getDay() { return day; }
    @Override
    public int getPatients() { return patients; }
    @Override
    public String getComment() { return comment; }

    @Override
    public void setDay(int day) { this.day = day; }
    @Override
    public void setPatients(int patients) { this.patients = patients; }
    @Override
    public void setComment(String comment) { this.comment = comment; }

    public Appointment() {
        this(0, 0, "");
    }

    public Appointment(int day, int patients, String comment) {
        this.day = day;
        this.patients = patients;
        this.comment = comment;
    }

}

class CompareByComment implements Comparator<AbstractAppointment> {
    @Override
    public int compare(AbstractAppointment o1, AbstractAppointment o2) {
        return o1.getComment().compareTo(o2.getComment());
    }
}

abstract class AbstractDoctor {
    public abstract String getName();
    public abstract int getExp();
    public abstract AbstractAppointment[] getApps();

    public abstract void setName(String name);
    public abstract void setExp(int exp);
    public abstract void setApps(AbstractAppointment... apps);

    abstract public void sortAppsByPatients();
    abstract public void sortAppsByComment();

    public void appendApp(AbstractAppointment app) {
        for (AbstractAppointment a : getApps()) {
            if (app.equals(a))
                return;
        }
        AbstractAppointment[] res = Arrays.copyOf(getApps(), getApps().length + 1);
        res[res.length - 1] = app;
        setApps(res);
    }

    public AbstractAppointment[] findApps(int pats) {
        AbstractAppointment[] res = new AbstractAppointment[0];
        for (AbstractAppointment app : getApps()) {
            if (app.getPatients() == pats) {
                res = Arrays.copyOf(res, res.length + 1);
                res[res.length - 1] = app;
            }
        }
        if (res.length == 0) return null;
        else return res;
    }

    public AbstractAppointment[] findApps(String comm) {
        AbstractAppointment[] res = new AbstractAppointment[0];
        for (AbstractAppointment app : getApps()) {
            if (app.getComment().equals(comm)) {
                res = Arrays.copyOf(res, res.length + 1);
                res[res.length - 1] = app;
            }
        }
        if (res.length == 0) return null;
        else return res;
    }

    @Override
    public String toString() {
        return getName() + ", experience: " + getExp() + ", appointments: " + getApps().length;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || !(obj instanceof AbstractDoctor)) {
            return false;
        }
        AbstractDoctor a = (AbstractDoctor) obj;
        return (getName() == a.getName()) && (getExp() == a.getExp()) && getApps().equals(a.getApps());
    }

    public double getAvgPatients() {
        double res = 0;
        for (AbstractAppointment a : getApps()) {
            res += a.getPatients();
        }
        res /= getApps().length;
        return res;
    }

    public AbstractAppointment getMinPatientsApp() {
        AbstractAppointment res = getApps()[0];
        for (AbstractAppointment a : getApps())
            if (a.getPatients() < res.getPatients())
                res = a;
        return res;
    }

    public AbstractAppointment getMaxCommentApp() {
        AbstractAppointment res = getApps()[0];
        for (AbstractAppointment a : getApps())
            if (a.getComment().length() > res.getComment().length())
                res = a;
        return res;
    }

    public void testTask() {
        Scanner in = new Scanner(System.in);
        System.out.println("Enter name, exp., num. of appointments:");
        String name = in.next();
        int exp = in.nextInt();
        int n = in.nextInt();

        Appointment[] apps = new Appointment[n];
        for (int i = 0; i < n; i++) {
            System.out.println("Enter day, num. of patients, comment:");
            int d = in.nextInt(), p = in.nextInt();
            String c = in.next();
            apps[i] = new Appointment(d, p, c);
        }

        this.setName(name);
        this.setExp(exp);
        this.setApps(apps);

        System.out.printf("Avg. num. of patients: %f\n" +
                        "App. with min. num. of patients: %d, %d, %s\n" +
                        "App. with max. length. of comment: %d, %d, %s\n",
                this.getAvgPatients(),
                this.getMinPatientsApp().getDay(), this.getMinPatientsApp().getPatients(), this.getMinPatientsApp().getComment(),
                this.getMaxCommentApp().getDay(), this.getMaxCommentApp().getPatients(), this.getMaxCommentApp().getComment());
        this.appendApp(new Appointment(1, 2, "append test"));
        this.sortAppsByPatients();
        System.out.println("Sort by patients:");
        for (AbstractAppointment a : this.getApps()) {
            System.out.println(a);
        }

        this.sortAppsByComment();
        System.out.println("Sort by comment:");
        for (AbstractAppointment a : this.getApps()) {
            System.out.println(a);
        }
    }
}

class Doctor extends AbstractDoctor {

    private String name;
    private int exp;
    private AbstractAppointment[] apps;

    public String getName() { return name; }
    public int getExp() { return exp; }
    public AbstractAppointment[] getApps() { return apps; }

    public void setName(String name) { this.name = name; }
    public void setExp(int exp) { this.exp = exp; }
    public void setApps(AbstractAppointment... apps) { this.apps = apps; }

    public Doctor(String name, int exp, AbstractAppointment... apps) {
        this.name = name;
        this.exp = exp;
        this.apps = apps;
    }

    public Doctor() {}

    public void sortAppsByPatients() {
        Arrays.sort(getApps());
    }

    public void sortAppsByComment() {
        Arrays.sort(getApps(), new CompareByComment());
    }
}

为什么Java在序列化时不写任何实际的类数据,如何解决?

编辑:我正在使用Java 8 SE。还要忽略TextDoctor,它工作正常,这是肯定的。

1 个答案:

答案 0 :(得分:0)

解决方案:由于某种原因,使每个继承的类都可序列化,从而解决了该问题。我仍然不知道为什么以及为什么。