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 name
,int exp
,AbstractAppointment[] apps
,这是我另一个类的对象的数组(不实现Serializable)。问题在于,序列化Java时,我只写类元数据(我想是吗?),而没有在文件中存储实际的类数据,反序列化时exp
为0,name
和apps
为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,它工作正常,这是肯定的。
答案 0 :(得分:0)
解决方案:由于某种原因,使每个继承的类都可序列化,从而解决了该问题。我仍然不知道为什么以及为什么。