Serialization and me -- or, How do I remove a Field?

J

James Aguilar

Suppose I have a class A that inherits from a Serializable class. Now I
have a class B that inherits from A. Now, suppose that I decide that I
would be better off having A and B inherit from a new abstract base class C
(which would itself inherit from A's parent). Here's the picture:

A <--- B

<--- A
C
<--- B

Now, suppose I want to maintain backwards compatibility. C has the field
that A used to have, and a simple readObject method works to transfer A's
field to C, but I can do no such thing with B. I'm not even strictly sure
what is happening when B is read, I just know that if I try to override
readObject with B, it cannot find the field that used to be in A. Any
advice?

- JFA1
 
T

Tom Dyess

James Aguilar said:
Suppose I have a class A that inherits from a Serializable class. Now I
have a class B that inherits from A. Now, suppose that I decide that I
would be better off having A and B inherit from a new abstract base class
C (which would itself inherit from A's parent). Here's the picture:

A <--- B

<--- A
C
<--- B

Now, suppose I want to maintain backwards compatibility. C has the field
that A used to have, and a simple readObject method works to transfer A's
field to C, but I can do no such thing with B. I'm not even strictly sure
what is happening when B is read, I just know that if I try to override
readObject with B, it cannot find the field that used to be in A. Any
advice?

- JFA1

Are you sure B is extending C? Sound like you forgot that. Got some skel
code?
 
J

James Aguilar

Tom Dyess said:
Are you sure B is extending C? Sound like you forgot that. Got some skel
code?

Tom,

I'm positive B is extending C. I will give you some skeleton code here.
The old way:

---- CODE ----
public class IfStatement extends SequentialBlock implements
Cloneable, Serializable {
static final long serialVersionUID = 1098192863719369933L;
protected ChainExpression test;

//Some methods here
}

public final class WhileStatement extends IfStatement {
static final long serialVersionUID = -6709545971510326304L;
int loopBound = 50;

//Some methods here
}
---- /CODE ----

And here's the new version:

---- CODE ----
public abstract class SingleConditionalStatement extends SequentialBlock
implements Serializable {
protected ChainExpression test;

//Methods
}

public final class IfStatement extends SingleConditionalStatement implements
Cloneable, Serializable {
static final long serialVersionUID = 1098192863719369933L;

private void readObject(java.io_ObjectInputStream in) throws IOException,
ClassNotFoundException {
if (test == null) {
test = (ChainExpression) in.readObject();
}
}

//Other methods
}

public final class WhileStatement extends SingleConditionalStatement
implements
java.io.Serializable {
static final long serialVersionUID = -6709545971510326304L;
int loopBound = 50;

private void readObject(java.io_ObjectInputStream in) throws IOException,
ClassNotFoundException {
if (test == null) {
test = (ChainExpression) in.readObject(); //This does not work
}
}

//Other methods
}
---- /CODE ----
 
T

Tom Dyess

James Aguilar said:
Tom,

I'm positive B is extending C. I will give you some skeleton code here.
The old way:

---- CODE ----
public class IfStatement extends SequentialBlock implements
Cloneable, Serializable {
static final long serialVersionUID = 1098192863719369933L;
protected ChainExpression test;

//Some methods here
}

public final class WhileStatement extends IfStatement {
static final long serialVersionUID = -6709545971510326304L;
int loopBound = 50;

//Some methods here
}
---- /CODE ----

And here's the new version:

---- CODE ----
public abstract class SingleConditionalStatement extends SequentialBlock
implements Serializable {
protected ChainExpression test;

//Methods
}

public final class IfStatement extends SingleConditionalStatement
implements
Cloneable, Serializable {
static final long serialVersionUID = 1098192863719369933L;

private void readObject(java.io_ObjectInputStream in) throws IOException,
ClassNotFoundException {
if (test == null) {
test = (ChainExpression) in.readObject();
}
}

//Other methods
}

public final class WhileStatement extends SingleConditionalStatement
implements
java.io.Serializable {
static final long serialVersionUID = -6709545971510326304L;
int loopBound = 50;

private void readObject(java.io_ObjectInputStream in) throws IOException,
ClassNotFoundException {
if (test == null) {
test = (ChainExpression) in.readObject(); //This does not work
}
}

//Other methods
}
---- /CODE ----

Strange - I don't have your SequentialBlock and ChainExpression objects, so
I replaced with Object and String respectively and it seems to work fine.
The IDE isn't complaining about not finding the protected test variable in
WhileStatement. Nothing in the code really jumped out at me; it looks fine.
Is your IDE complaining that it can't find the test variable in
WhileStatement? If you are using Eclipse, it might be getting confused. Try
turning off the auto compile and do a manual build.

public abstract class SingleConditionalStatement extends Object
implements Serializable {
protected String test;

//Methods
}

public final class IfStatement extends SingleConditionalStatement implements
Cloneable, Serializable {
static final long serialVersionUID = 1098192863719369933L;

private void readObject(java.io_ObjectInputStream in) throws IOException,
ClassNotFoundException {
if (test == null) {
test = (String) in.readObject();
}
}

//Other methods
}

public final class WhileStatement extends SingleConditionalStatement
implements
java.io.Serializable {
static final long serialVersionUID = -6709545971510326304L;
int loopBound = 50;

private void readObject(java.io_ObjectInputStream in) throws IOException,
ClassNotFoundException {
if (test == null) {
test = (String) in.readObject(); //This does not work
}
}

//Other methods
}
 
J

James Aguilar

Tom Dyess said:
Strange - I don't have your SequentialBlock and ChainExpression objects,
so I replaced with Object and String respectively and it seems to work
fine. The IDE isn't complaining about not finding the protected test
variable in WhileStatement. Nothing in the code really jumped out at me;
it looks fine. Is your IDE complaining that it can't find the test
variable in WhileStatement? If you are using Eclipse, it might be getting
confused. Try turning off the auto compile and do a manual build.

It's not about compile errors. It's about deserializing saved objects from
a binary file. It's not having trouble with that?

- JFA1
 
T

Thomas Bühler

Hi,
It's not an easy way to make this work.
You have to write your own deserialization mechanism.
Implement your own 'private readObject(ObjectInputStream in)' Method and do
the deserialization in your code.
It is not easy to handle all the problems with superclasses and old classes.

An example how a possible solution might look, you also have to implement
such a method in the superclass:

private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {

ObjectInputStream.GetField fields = in.readFields(); // magic
try {
// Deserialization Members from superclass.
readBasicFields(fields, this);
// End deserialization Members from superclass.
} catch (Exception e) {
}
// Deserialization Members from this class.
myString = (String) fields.get("myString", null);
.....
}

Best regards.
Thomas Bühler
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top