Reputation: 7
I have the following class that allows me to serialize objects in my program:
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class Persistor<T> {
private T data;
public void save(T data, String file) {
try {
FileOutputStream os = new FileOutputStream(file);
XMLEncoder encoder = new XMLEncoder(os);
encoder.writeObject(data);
encoder.close();
} catch(FileNotFoundException e) {
System.out.println("File not found");
}
}
@SuppressWarnings({ "unchecked", "finally" })
public T read(String file) {
try {
FileInputStream fis = new FileInputStream(file);
XMLDecoder decoder = new XMLDecoder(fis);
data = (T)decoder.readObject();
decoder.close();
} catch(FileNotFoundException e) {
System.out.println("File not found");
} finally {
return data;
}
}
}
The thing is that I have my bussiness logic package with classes like student and it seems like I need to have an empty constructor public Student() {}
to get the program working:
package logic;
public class Student {
private String name;
public Student(String name) {
this.name = name;
} public Student() {} // empty constructor
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
If I take out the empty constructor, the following exceptions appear on the console:
java.lang.InstantiationException: logic.Student
Continuing ...
java.lang.IllegalStateException: The outer element does not return value
Continuing ...
Is there any way to fix this stuff, I mean by not having the empty constructor? Because I have like 7 more classes where everyone needs to have it's own empty constructor.
Upvotes: 1
Views: 2325
Reputation: 136042
You can try ConstructorProperties
annotation
public class Student {
private String name;
@ConstructorProperties("name")
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
test
public class Test1 {
public static void main(String[] args) throws Exception {
Student s1 = new Student("Jon");
XMLEncoder encoder = new XMLEncoder(new FileOutputStream("xxx"));
encoder.writeObject(s1);
encoder.close();
XMLDecoder decoder = new XMLDecoder(new FileInputStream("xxx"));
Student s2 = (Student)decoder.readObject();
decoder.close();
System.out.println(s2);
}
}
output
test.Student@e3fd79
Upvotes: 1
Reputation: 6510
You are attempting to deserialize a bean. The way most serialization frameworks including XMLEncoder/Decoder go about this is by instantiating a default no-arg constructor and then reflectively calling the getters or setters for each one of the member objects.
The documentation seems to support this...
XMLDecoder javadoc:
The XMLDecoder class is used to read XML documents created using the XMLEncoder and is used just like the ObjectInputStream.
ObjectInputStream javadoc:
Reading an object is analogous to running the constructors of a new object. Memory is allocated for the object and initialized to zero (NULL). No-arg constructors are invoked for the non-serializable classes and then the fields of the serializable classes are restored from the stream starting with the serializable class closest to java.lang.object and finishing with the object's most specific class.
...
Serialization does not read or assign values to the fields of any object that does not implement the java.io.Serializable interface. Subclasses of Objects that are not serializable can be serializable. In this case the non-serializable class must have a no-arg constructor to allow its fields to be initialized. In this case it is the responsibility of the subclass to save and restore the state of the non-serializable class. It is frequently the case that the fields of that class are accessible (public, package, or protected) or that there are get and set methods that can be used to restore the state.
From the documentation you can see that your options are either to implement Serializable or add the no-arg constructor and keep getters and setters for all your fields.
Upvotes: 0