简体   繁体   中英

Java object loses all data on 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");

    }
}

I have an object of type SerialDoctor that's serializable and need to be serialized into input.dat to be read later into another SerialDoctor object. SerialDoctor inherits fields String name , int exp , AbstractAppointment[] apps which is an array of object of my another class (doesn't implement Serializable). The problem is that when serializing Java only writes class metadata (I guess?) and doesn't store the actual class data in file, and on deserialization exp is 0, name and apps are nulls, so trying to work with the data (which is lost) yields NullPointerException. Here are classes that are being extended by 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());
    }
}

Why Java doesn't write any actual class data on serialization and how can it be fixed?

Edit: I'm using Java 8 SE. Also ignore TextDoctor, it's working fine, that's for sure.

Solution: for some reason making every inherited class serializable fixed the problem. I still don't know why and how though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM